40 #if V8_TARGET_ARCH_IA32
42 #elif V8_TARGET_ARCH_X64
44 #elif V8_TARGET_ARCH_ARM
46 #elif V8_TARGET_ARCH_MIPS
49 #error Unsupported target architecture.
56 : block_id_(graph->GetNextBlockID()),
58 phis_(4, graph->zone()),
62 loop_information_(
NULL),
63 predecessors_(2, graph->zone()),
65 dominated_blocks_(4, graph->zone()),
66 last_environment_(
NULL),
68 first_instruction_index_(-1),
69 last_instruction_index_(-1),
70 deleted_phis_(4, graph->zone()),
71 parent_loop_header_(
NULL),
72 is_inline_return_target_(
false),
73 is_deoptimizing_(
false),
74 dominates_loop_successors_(
false) { }
85 loop_information_ =
NULL;
91 phis_.Add(phi,
zone());
98 ASSERT(phis_.Contains(phi));
101 phis_.RemoveElement(phi);
110 if (first_ ==
NULL) {
112 entry->InitializeAsFirst(
this);
113 first_ = last_ = entry;
127 for (
int i = 0; i < environment->
length(); i++) {
136 HSimulate* HBasicBlock::CreateSimulate(
int ast_id) {
140 environment->closure()->shared()->VerifyBailoutId(ast_id));
142 int push_count = environment->push_count();
143 int pop_count = environment->pop_count();
145 HSimulate* instr =
new(
zone()) HSimulate(ast_id, pop_count,
zone());
146 for (
int i = push_count - 1; i >= 0; --i) {
147 instr->AddPushedValue(environment->ExpressionStackAt(i));
149 for (
int i = 0; i < environment->assigned_variables()->length(); ++i) {
150 int index = environment->assigned_variables()->at(i);
151 instr->AddAssignedValue(index, environment->Lookup(index));
153 environment->ClearHistory();
162 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
163 it.Current()->RegisterPredecessor(
this);
208 int length = predecessors_.length();
210 for (
int i = 0; i < length; i++) {
217 ->VerifyBailoutId(ast_id));
218 simulate->set_ast_id(ast_id);
225 while (current !=
NULL) {
226 if (current ==
this)
return true;
262 void HBasicBlock::RegisterPredecessor(
HBasicBlock* pred) {
271 for (
int i = 0; i < phis_.length(); ++i) {
272 phis_[i]->AddInput(incoming_env->
values()->at(i));
282 predecessors_.Add(pred,
zone());
286 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
287 ASSERT(!dominated_blocks_.Contains(block));
291 while (index < dominated_blocks_.length() &&
292 dominated_blocks_[index]->block_id() < block->block_id()) {
295 dominated_blocks_.InsertAt(index, block,
zone());
300 if (dominator_ ==
NULL) {
302 other->AddDominatedBlock(
this);
307 while (first != second) {
316 if (dominator_ != first) {
317 ASSERT(dominator_->dominated_blocks_.Contains(
this));
318 dominator_->dominated_blocks_.RemoveElement(
this);
320 first->AddDominatedBlock(
this);
337 int outstanding_successors = 1;
342 for (HPredecessorIterator it(dominator_candidate); !it.Done();
347 outstanding_successors--;
359 ASSERT(outstanding_successors >= 0);
361 if (outstanding_successors == 0 &&
362 (parent_loop_header ==
this && !dominator_candidate->
IsLoopHeader())) {
366 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
375 outstanding_successors++;
383 for (
int i = 0; i < predecessors_.length(); ++i) {
384 if (predecessors_[i] == predecessor)
return i;
392 void HBasicBlock::Verify() {
398 if (predecessors_.length() > 1) {
399 for (
int i = 0; i < predecessors_.length(); ++i) {
408 this->back_edges_.Add(block, block->
zone());
416 for (
int i = 0; i < back_edges_.length(); ++i) {
427 void HLoopInformation::AddBlock(
HBasicBlock* block) {
434 blocks_.Add(block, block->
zone());
435 for (
int i = 0; i < block->
predecessors()->length(); ++i) {
451 ReachabilityAnalyzer(HBasicBlock* entry_block,
453 HBasicBlock* dont_visit)
455 stack_(16, entry_block->zone()),
456 reachable_(block_count, entry_block->zone()),
457 dont_visit_(dont_visit) {
458 PushBlock(entry_block);
462 int visited_count()
const {
return visited_count_; }
463 const BitVector* reachable()
const {
return &reachable_; }
466 void PushBlock(HBasicBlock* block) {
467 if (block !=
NULL && block != dont_visit_ &&
468 !reachable_.Contains(block->block_id())) {
469 reachable_.Add(block->block_id());
470 stack_.Add(block, block->zone());
476 while (!stack_.is_empty()) {
477 HControlInstruction* end = stack_.RemoveLast()->end();
478 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
479 PushBlock(it.Current());
485 ZoneList<HBasicBlock*> stack_;
486 BitVector reachable_;
487 HBasicBlock* dont_visit_;
491 void HGraph::Verify(
bool do_full_verify)
const {
492 for (
int i = 0; i < blocks_.length(); i++) {
493 HBasicBlock* block = blocks_.at(i);
499 HInstruction* current = block->first();
500 ASSERT(current !=
NULL && current->IsBlockEntry());
501 while (current !=
NULL) {
502 ASSERT((current->next() ==
NULL) == current->IsControlInstruction());
503 ASSERT(current->block() == block);
505 current = current->next();
509 HBasicBlock* first = block->end()->FirstSuccessor();
510 HBasicBlock* second = block->end()->SecondSuccessor();
515 ASSERT(first->predecessors()->Contains(block));
516 if (second !=
NULL) {
517 ASSERT(second->predecessors()->Contains(block));
522 for (
int j = 0; j < block->phis()->length(); j++) {
523 HPhi* phi = block->phis()->at(j);
529 if (block->predecessors()->length() >= 2) {
530 int id = block->predecessors()->first()->last_environment()->ast_id();
531 for (
int k = 0; k < block->predecessors()->length(); k++) {
532 HBasicBlock* predecessor = block->predecessors()->at(k);
533 ASSERT(predecessor->end()->IsGoto());
534 ASSERT(predecessor->last_environment()->ast_id() == id);
540 ASSERT(blocks_.at(0)->predecessors()->is_empty());
542 if (do_full_verify) {
544 ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(),
NULL);
545 ASSERT(analyzer.visited_count() == blocks_.length());
551 for (
int i = 0; i < blocks_.length(); ++i) {
552 HBasicBlock* block = blocks_.at(i);
553 if (block->dominator() ==
NULL) {
558 ReachabilityAnalyzer dominator_analyzer(entry_block_,
561 ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id()));
570 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
572 if (!pointer->is_set()) {
573 HConstant* constant =
new(
zone()) HConstant(Handle<Object>(value),
576 pointer->set(constant);
578 return pointer->get();
588 return GetConstant(&constant_minus1_,
Smi::FromInt(-1));
593 return GetConstant(&constant_true_,
isolate()->heap()->true_value());
598 return GetConstant(&constant_false_,
isolate()->heap()->false_value());
603 return GetConstant(&constant_hole_,
isolate()->heap()->the_hole_value());
608 TypeFeedbackOracle* oracle,
610 : function_state_(
NULL),
615 current_block_(
NULL),
619 inline_bailout_(
false) {
623 function_state_= &initial_function_state_;
631 }
else if (second ==
NULL) {
635 first->
Goto(join_block);
636 second->
Goto(join_block);
646 if (continue_block !=
NULL) {
647 if (exit_block !=
NULL) exit_block->
Goto(continue_block);
649 return continue_block;
655 HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
656 HBasicBlock* loop_entry,
657 HBasicBlock* body_exit,
658 HBasicBlock* loop_successor,
659 HBasicBlock* break_block) {
660 if (body_exit !=
NULL) body_exit->
Goto(loop_entry);
661 loop_entry->PostProcessLoopHeader(statement);
662 if (break_block !=
NULL) {
663 if (loop_successor !=
NULL) loop_successor->Goto(break_block);
664 break_block->SetJoinId(statement->ExitId());
667 return loop_successor;
678 : isolate_(info->isolate()),
685 is_recursive_(
false) {
697 if (FLAG_trace_bailout) {
698 PrintF(
"Not enough virtual registers for (values).\n");
702 LAllocator allocator(values,
this);
703 LChunkBuilder builder(info,
this, &allocator);
704 LChunk* chunk = builder.Build();
707 if (!allocator.Allocate(chunk)) {
708 if (FLAG_trace_bailout) {
709 PrintF(
"Not enough virtual registers (regalloc).\n");
715 LCodeGen generator(chunk, &assembler, info, zone);
719 if (generator.GenerateCode()) {
720 if (FLAG_trace_codegen) {
721 PrintF(
"Crankshaft Compiler - ");
727 generator.FinishCode(code);
737 blocks_.Add(result,
zone());
743 if (!FLAG_use_canonicalizing)
return;
744 HPhase phase(
"H_Canonicalize",
this);
745 for (
int i = 0; i <
blocks()->length(); ++i) {
747 while (instr !=
NULL) {
750 instr = instr->
next();
757 HPhase phase(
"H_Block ordering");
762 Postorder(start, &visited, &reverse_result,
NULL);
766 for (
int i = reverse_result.length() - 1; i >= 0; --i) {
768 blocks_.Add(b,
zone());
778 for (
int i = 0; i < loop->
blocks()->length(); ++i) {
780 for (HSuccessorIterator it(b->
end()); !it.Done(); it.Advance()) {
781 Postorder(it.Current(), visited, order, loop_header);
790 void HGraph::Postorder(HBasicBlock* block,
792 ZoneList<HBasicBlock*>* order,
793 HBasicBlock* loop_header) {
794 if (block ==
NULL || visited->Contains(block->block_id()))
return;
795 if (block->parent_loop_header() != loop_header)
return;
796 visited->Add(block->block_id());
797 if (block->IsLoopHeader()) {
798 PostorderLoopBlocks(block->loop_information(), visited, order, loop_header);
799 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
800 Postorder(it.Current(), visited, order, block);
803 ASSERT(block->IsFinished());
804 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
805 Postorder(it.Current(), visited, order, loop_header);
808 ASSERT(block->end()->FirstSuccessor() ==
NULL ||
809 order->Contains(block->end()->FirstSuccessor()) ||
810 block->end()->FirstSuccessor()->IsLoopHeader());
811 ASSERT(block->end()->SecondSuccessor() ==
NULL ||
812 order->Contains(block->end()->SecondSuccessor()) ||
813 block->end()->SecondSuccessor()->IsLoopHeader());
814 order->Add(block,
zone());
819 HPhase phase(
"H_Assign dominators",
this);
820 for (
int i = 0; i < blocks_.length(); ++i) {
828 for (
int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
829 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
838 HPhase phase(
"H_Propagate deoptimizing mark",
this);
842 void HGraph::MarkAsDeoptimizingRecursively(
HBasicBlock* block) {
846 MarkAsDeoptimizingRecursively(dominated);
851 HPhase phase(
"H_Redundant phi elimination",
this);
857 for (
int i = 0; i < blocks_.length(); ++i) {
861 while (!worklist.is_empty()) {
862 HPhi* phi = worklist.RemoveLast();
866 if (block ==
NULL)
continue;
871 if (replacement !=
NULL) {
873 for (HUseIterator it(phi->
uses()); !it.Done(); it.Advance()) {
874 HValue* value = it.value();
885 HPhase phase(
"H_Unreachable phi elimination",
this);
890 for (
int i = 0; i < blocks_.length(); ++i) {
891 for (
int j = 0; j < blocks_[i]->phis()->length(); j++) {
892 HPhi* phi = blocks_[i]->phis()->at(j);
899 worklist.Add(phi,
zone());
905 while (!worklist.is_empty()) {
906 HPhi* phi = worklist.RemoveLast();
917 for (
int i = 0; i <
phi_list.length(); i++) {
929 int block_count = blocks_.length();
930 for (
int i = 0; i < block_count; ++i) {
931 for (
int j = 0; j < blocks_[i]->phis()->length(); ++j) {
932 HPhi* phi = blocks_[i]->phis()->at(j);
942 int block_count = blocks_.length();
943 for (
int i = 0; i < block_count; ++i) {
944 for (
int j = 0; j < blocks_[i]->phis()->length(); ++j) {
945 HPhi* phi = blocks_[i]->phis()->at(j);
957 int block_count = blocks_.length();
959 for (
int i = 0; i < block_count; ++i) {
960 for (
int j = 0; j < blocks_[i]->phis()->length(); ++j) {
961 HPhi* phi = blocks_[i]->phis()->at(j);
962 phi_list_->Add(phi,
zone());
970 for (
int i = 0; i < worklist->length(); ++i) {
971 ASSERT(!in_worklist.Contains(worklist->
at(i)->id()));
972 in_worklist.Add(worklist->
at(i)->id());
975 while (!worklist->is_empty()) {
976 HValue* current = worklist->RemoveLast();
977 in_worklist.
Remove(current->id());
978 if (current->UpdateInferredType()) {
979 for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) {
980 HValue* use = it.value();
981 if (!in_worklist.Contains(use->id())) {
982 in_worklist.Add(use->id());
994 graph_(graph), zone_(graph->zone()), changed_ranges_(16, zone_) { }
999 void TraceRange(
const char* msg, ...);
1003 void InferRange(
HValue* value);
1004 void RollBackTo(
int index);
1013 void HRangeAnalysis::TraceRange(
const char* msg, ...) {
1014 if (FLAG_trace_range) {
1016 va_start(arguments, msg);
1023 void HRangeAnalysis::Analyze() {
1024 HPhase phase(
"H_Range analysis", graph_);
1025 Analyze(graph_->entry_block());
1029 void HRangeAnalysis::Analyze(HBasicBlock* block) {
1030 TraceRange(
"Analyzing block B%d\n", block->block_id());
1032 int last_changed_range = changed_ranges_.length() - 1;
1035 if (block->predecessors()->length() == 1) {
1037 if (pred->end()->IsCompareIDAndBranch()) {
1043 for (
int i = 0; i < block->phis()->length(); ++i) {
1044 HPhi* phi = block->phis()->at(i);
1049 HInstruction* instr = block->first();
1050 while (instr != block->end()) {
1052 instr = instr->next();
1056 for (
int i = 0; i < block->dominated_blocks()->length(); ++i) {
1057 Analyze(block->dominated_blocks()->at(i));
1060 RollBackTo(last_changed_range);
1064 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test,
1065 HBasicBlock* dest) {
1066 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
1067 if (test->GetInputRepresentation().IsInteger32()) {
1069 if (test->SecondSuccessor() == dest) {
1073 UpdateControlFlowRange(op, test->left(), test->right());
1074 UpdateControlFlowRange(inverted_op, test->right(), test->left());
1081 void HRangeAnalysis::UpdateControlFlowRange(
Token::Value op,
1085 Range* range = other->range() !=
NULL ? other->range() : &temp_range;
1086 Range* new_range =
NULL;
1088 TraceRange(
"Control flow range infer %d %s %d\n",
1093 if (op ==
Token::EQ || op == Token::EQ_STRICT) {
1095 new_range = range->Copy(zone_);
1096 }
else if (op == Token::LT || op == Token::LTE) {
1097 new_range = range->CopyClearLower(zone_);
1098 if (op == Token::LT) {
1099 new_range->AddConstant(-1);
1101 }
else if (op == Token::GT || op == Token::GTE) {
1102 new_range = range->CopyClearUpper(zone_);
1103 if (op == Token::GT) {
1104 new_range->AddConstant(1);
1108 if (new_range !=
NULL && !new_range->IsMostGeneric()) {
1114 void HRangeAnalysis::InferRange(HValue* value) {
1115 ASSERT(!value->HasRange());
1116 if (!value->representation().IsNone()) {
1117 value->ComputeInitialRange(zone_);
1118 Range* range = value->range();
1119 TraceRange(
"Initial inferred range of %d (%s) set to [%d,%d]\n",
1128 void HRangeAnalysis::RollBackTo(
int index) {
1129 for (
int i = index + 1; i < changed_ranges_.length(); ++i) {
1130 changed_ranges_[i]->RemoveLastAddedRange();
1132 changed_ranges_.Rewind(index + 1);
1137 Range* original_range = value->range();
1138 value->AddNewRange(range, zone_);
1139 changed_ranges_.Add(value, zone_);
1140 Range* new_range = value->range();
1141 TraceRange(
"Updated range of %d set to [%d,%d]\n",
1144 new_range->upper());
1145 if (original_range !=
NULL) {
1146 TraceRange(
"Original range was [%d,%d]\n",
1147 original_range->lower(),
1148 original_range->upper());
1150 TraceRange(
"New information was [%d,%d]\n",
1158 va_start(arguments, msg);
1165 #define TRACE_GVN_1(msg, a1) \
1166 if (FLAG_trace_gvn) { \
1167 TraceGVN(msg, a1); \
1170 #define TRACE_GVN_2(msg, a1, a2) \
1171 if (FLAG_trace_gvn) { \
1172 TraceGVN(msg, a1, a2); \
1175 #define TRACE_GVN_3(msg, a1, a2, a3) \
1176 if (FLAG_trace_gvn) { \
1177 TraceGVN(msg, a1, a2, a3); \
1180 #define TRACE_GVN_4(msg, a1, a2, a3, a4) \
1181 if (FLAG_trace_gvn) { \
1182 TraceGVN(msg, a1, a2, a3, a4); \
1185 #define TRACE_GVN_5(msg, a1, a2, a3, a4, a5) \
1186 if (FLAG_trace_gvn) { \
1187 TraceGVN(msg, a1, a2, a3, a4, a5); \
1192 : array_size_(other->array_size_),
1193 lists_size_(other->lists_size_),
1194 count_(other->count_),
1195 present_flags_(other->present_flags_),
1196 array_(zone->
NewArray<HValueMapListElement>(other->array_size_)),
1197 lists_(zone->
NewArray<HValueMapListElement>(other->lists_size_)),
1198 free_list_head_(other->free_list_head_) {
1199 memcpy(array_, other->array_, array_size_ *
sizeof(HValueMapListElement));
1200 memcpy(lists_, other->lists_, lists_size_ *
sizeof(HValueMapListElement));
1205 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(flags);
1206 if (!present_flags_.ContainsAnyOf(depends_flags))
return;
1207 present_flags_.RemoveAll();
1208 for (
int i = 0; i < array_size_; ++i) {
1209 HValue* value = array_[i].value;
1210 if (value !=
NULL) {
1214 for (
int current = array_[i].next; current != kNil; current = next) {
1215 next = lists_[current].next;
1216 HValue* value = lists_[current].value;
1220 lists_[current].next = free_list_head_;
1221 free_list_head_ = current;
1224 lists_[current].next = kept;
1229 array_[i].next = kept;
1232 value = array_[i].value;
1235 int head = array_[i].next;
1237 array_[i].value =
NULL;
1239 array_[i].value = lists_[head].value;
1240 array_[i].next = lists_[head].next;
1241 lists_[head].next = free_list_head_;
1242 free_list_head_ = head;
1253 uint32_t hash =
static_cast<uint32_t
>(value->
Hashcode());
1254 uint32_t pos = Bound(hash);
1255 if (array_[pos].value !=
NULL) {
1256 if (array_[pos].value->
Equals(value))
return array_[pos].value;
1257 int next = array_[pos].next;
1258 while (next != kNil) {
1259 if (lists_[next].value->
Equals(value))
return lists_[next].value;
1260 next = lists_[next].next;
1267 void HValueMap::Resize(
int new_size,
Zone* zone) {
1268 ASSERT(new_size > count_);
1273 if (free_list_head_ == kNil) {
1274 ResizeLists(lists_size_ << 1, zone);
1277 HValueMapListElement* new_array =
1278 zone->
NewArray<HValueMapListElement>(new_size);
1279 memset(new_array, 0,
sizeof(HValueMapListElement) * new_size);
1281 HValueMapListElement* old_array = array_;
1282 int old_size = array_size_;
1284 int old_count = count_;
1287 array_size_ = new_size;
1290 if (old_array !=
NULL) {
1292 for (
int i = 0; i < old_size; ++i) {
1293 if (old_array[i].value !=
NULL) {
1294 int current = old_array[i].next;
1295 while (current != kNil) {
1296 Insert(lists_[current].value, zone);
1297 int next = lists_[current].next;
1298 lists_[current].next = free_list_head_;
1299 free_list_head_ = current;
1303 Insert(old_array[i].value, zone);
1308 ASSERT(count_ == old_count);
1312 void HValueMap::ResizeLists(
int new_size, Zone* zone) {
1313 ASSERT(new_size > lists_size_);
1315 HValueMapListElement* new_lists =
1316 zone->NewArray<HValueMapListElement>(new_size);
1317 memset(new_lists, 0,
sizeof(HValueMapListElement) * new_size);
1319 HValueMapListElement* old_lists = lists_;
1320 int old_size = lists_size_;
1322 lists_size_ = new_size;
1325 if (old_lists !=
NULL) {
1326 memcpy(lists_, old_lists, old_size *
sizeof(HValueMapListElement));
1328 for (
int i = old_size; i < lists_size_; ++i) {
1329 lists_[i].next = free_list_head_;
1330 free_list_head_ = i;
1335 void HValueMap::Insert(HValue* value, Zone* zone) {
1338 if (count_ >= array_size_ >> 1) Resize(array_size_ << 1, zone);
1339 ASSERT(count_ < array_size_);
1341 uint32_t pos = Bound(static_cast<uint32_t>(value->Hashcode()));
1342 if (array_[pos].value ==
NULL) {
1343 array_[pos].value = value;
1344 array_[pos].next = kNil;
1346 if (free_list_head_ == kNil) {
1347 ResizeLists(lists_size_ << 1, zone);
1349 int new_element_pos = free_list_head_;
1350 ASSERT(new_element_pos != kNil);
1351 free_list_head_ = lists_[free_list_head_].next;
1352 lists_[new_element_pos].value = value;
1353 lists_[new_element_pos].next = array_[pos].next;
1354 ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value !=
NULL);
1355 array_[pos].next = new_element_pos;
1360 HSideEffectMap::HSideEffectMap() : count_(0) {
1365 HSideEffectMap::HSideEffectMap(HSideEffectMap* other) : count_(other->count_) {
1370 HSideEffectMap& HSideEffectMap::operator= (
const HSideEffectMap& other) {
1371 if (
this != &other) {
1380 if (flags.Contains(changes_flag)) {
1381 if (data_[i] !=
NULL) count_--;
1388 void HSideEffectMap::Store(
GVNFlagSet flags, HInstruction* instr) {
1391 if (flags.Contains(changes_flag)) {
1392 if (data_[i] ==
NULL) count_++;
1410 void HStackCheckEliminator::Process() {
1415 for (
int i = 0; i < graph_->blocks()->length(); i++) {
1416 HBasicBlock* block = graph_->
blocks()->at(i);
1417 if (block->IsLoopHeader()) {
1418 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
1419 HBasicBlock* dominator = back_edge;
1421 HInstruction* instr = dominator->first();
1422 while (instr !=
NULL) {
1423 if (instr->IsCall()) {
1424 block->loop_information()->stack_check()->Eliminate();
1427 instr = instr->next();
1431 if (dominator == block)
break;
1434 dominator = dominator->dominator();
1445 : capacity_(capacity),
1447 dense_(zone->
NewArray<int>(capacity)),
1448 sparse_(zone->
NewArray<int>(capacity)) {
1451 memset(sparse_, 0,
sizeof(sparse_[0]) * capacity);
1456 ASSERT(0 <= n && n < capacity_);
1458 return 0 <= d && d < length_ && dense_[d] == n;
1463 dense_[length_] = n;
1464 sparse_[n] = length_;
1486 removed_side_effects_(
false),
1487 block_side_effects_(graph->blocks()->length(), graph->zone()),
1488 loop_side_effects_(graph->blocks()->length(), graph->zone()),
1489 visited_on_paths_(graph->zone(), graph->blocks()->length()) {
1490 ASSERT(info->isolate()->heap()->allow_allocation(
false));
1491 block_side_effects_.AddBlock(
GVNFlagSet(), graph_->blocks()->length(),
1493 loop_side_effects_.AddBlock(
GVNFlagSet(), graph_->blocks()->length(),
1497 ASSERT(!info_->isolate()->heap()->allow_allocation(
true));
1504 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
1507 void AnalyzeGraph();
1508 void ComputeBlockSideEffects();
1509 void LoopInvariantCodeMotion();
1515 bool AllowCodeMotion();
1518 HGraph* graph() {
return graph_; }
1519 CompilationInfo* info() {
return info_; }
1520 Zone* zone()
const {
return graph_->
zone(); }
1523 CompilationInfo* info_;
1524 bool removed_side_effects_;
1527 ZoneList<GVNFlagSet> block_side_effects_;
1530 ZoneList<GVNFlagSet> loop_side_effects_;
1534 SparseSet visited_on_paths_;
1538 bool HGlobalValueNumberer::Analyze() {
1539 removed_side_effects_ =
false;
1540 ComputeBlockSideEffects();
1541 if (FLAG_loop_invariant_code_motion) {
1542 LoopInvariantCodeMotion();
1545 return removed_side_effects_;
1549 void HGlobalValueNumberer::ComputeBlockSideEffects() {
1553 for (
int i = 0; i < loop_side_effects_.length(); ++i) {
1554 loop_side_effects_[i].RemoveAll();
1556 for (
int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1558 HBasicBlock* block = graph_->blocks()->at(i);
1559 HInstruction* instr = block->first();
1560 int id = block->block_id();
1562 while (instr !=
NULL) {
1563 side_effects.
Add(instr->ChangesFlags());
1564 if (instr->IsSoftDeoptimize()) {
1565 block_side_effects_[id].RemoveAll();
1566 side_effects.RemoveAll();
1569 instr = instr->next();
1571 block_side_effects_[id].Add(side_effects);
1574 if (block->IsLoopHeader()) {
1575 loop_side_effects_[id].Add(side_effects);
1579 if (block->HasParentLoopHeader()) {
1580 int header_id = block->parent_loop_header()->block_id();
1581 loop_side_effects_[header_id].Add(block->IsLoopHeader()
1582 ? loop_side_effects_[id]
1590 char underlying_buffer[
kLastFlag * 128];
1591 Vector<char> buffer(underlying_buffer,
sizeof(underlying_buffer));
1594 const char* separator =
"";
1595 const char* comma =
", ";
1597 uint32_t set_depends_on = 0;
1598 uint32_t set_changes = 0;
1599 for (
int bit = 0; bit <
kLastFlag; ++bit) {
1600 if ((flags.
ToIntegral() & (1 << bit)) != 0) {
1608 bool positive_changes = set_changes < (kLastFlag / 2);
1609 bool positive_depends_on = set_depends_on < (kLastFlag / 2);
1610 if (set_changes > 0) {
1611 if (positive_changes) {
1614 offset +=
OS::SNPrintF(buffer + offset,
"changes all except [");
1616 for (
int bit = 0; bit <
kLastFlag; ++bit) {
1617 if (((flags.
ToIntegral() & (1 << bit)) != 0) == positive_changes) {
1618 switch (static_cast<GVNFlag>(bit)) {
1619 #define DECLARE_FLAG(type) \
1620 case kChanges##type: \
1621 offset += OS::SNPrintF(buffer + offset, separator); \
1622 offset += OS::SNPrintF(buffer + offset, #type); \
1623 separator = comma; \
1635 if (set_depends_on > 0) {
1637 if (set_changes > 0) {
1640 if (positive_depends_on) {
1641 offset +=
OS::SNPrintF(buffer + offset,
"depends on [");
1643 offset +=
OS::SNPrintF(buffer + offset,
"depends on all except [");
1645 for (
int bit = 0; bit <
kLastFlag; ++bit) {
1646 if (((flags.
ToIntegral() & (1 << bit)) != 0) == positive_depends_on) {
1647 switch (static_cast<GVNFlag>(bit)) {
1648 #define DECLARE_FLAG(type) \
1649 case kDependsOn##type: \
1650 offset += OS::SNPrintF(buffer + offset, separator); \
1651 offset += OS::SNPrintF(buffer + offset, #type); \
1652 separator = comma; \
1667 size_t string_len = strlen(underlying_buffer) + 1;
1668 ASSERT(string_len <=
sizeof(underlying_buffer));
1669 char* result =
new char[strlen(underlying_buffer) + 1];
1670 memcpy(result, underlying_buffer, string_len);
1675 void HGlobalValueNumberer::LoopInvariantCodeMotion() {
1676 for (
int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1677 HBasicBlock* block = graph_->blocks()->at(i);
1678 if (block->IsLoopHeader()) {
1679 GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
1680 TRACE_GVN_2(
"Try loop invariant motion for block B%d %s\n",
1686 HBasicBlock* last = block->loop_information()->GetLastBackEdge();
1687 for (
int j = block->block_id(); j <= last->block_id(); ++j) {
1688 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects,
1689 &accumulated_first_time_depends,
1690 &accumulated_first_time_changes);
1697 void HGlobalValueNumberer::ProcessLoopBlock(
1699 HBasicBlock* loop_header,
1703 HBasicBlock* pre_header = loop_header->predecessors()->at(0);
1708 HInstruction* instr = block->first();
1709 while (instr !=
NULL) {
1710 HInstruction* next = instr->next();
1711 bool hoisted =
false;
1713 TRACE_GVN_4(
"Checking instruction %d (%s) %s. Loop %s\n",
1718 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags);
1719 if (instr->IsTransitionElementsKind()) {
1730 hoist_change_blockers.
Add(kChangesElementsKind);
1732 if (trans->original_map()->has_fast_double_elements()) {
1733 hoist_change_blockers.Add(kChangesElementsPointer);
1734 hoist_change_blockers.Add(kChangesDoubleArrayElements);
1736 if (trans->transitioned_map()->has_fast_double_elements()) {
1737 hoist_change_blockers.Add(kChangesElementsPointer);
1738 hoist_change_blockers.Add(kChangesArrayElements);
1740 if (FLAG_trace_gvn) {
1741 GVNFlagSet hoist_blockers = hoist_depends_blockers;
1742 hoist_blockers.
Add(hoist_change_blockers);
1744 first_time.
Add(*first_time_depends);
1745 TRACE_GVN_4(
"Checking dependencies on HTransitionElementsKind "
1746 "%d (%s) hoist blockers: %s; "
1747 "first-time accumulated: %s\n",
1757 bool in_nested_loop = block != loop_header &&
1758 ((block->parent_loop_header() != loop_header) ||
1759 block->IsLoopHeader());
1760 can_hoist = !in_nested_loop &&
1761 block->IsLoopSuccessorDominator() &&
1762 !first_time_depends->ContainsAnyOf(hoist_depends_blockers) &&
1763 !first_time_changes->ContainsAnyOf(hoist_change_blockers);
1767 bool inputs_loop_invariant =
true;
1768 for (
int i = 0; i < instr->OperandCount(); ++i) {
1769 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
1770 inputs_loop_invariant =
false;
1774 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) {
1775 TRACE_GVN_1(
"Hoisting loop invariant instruction %d\n", instr->id());
1778 instr->InsertBefore(pre_header->end());
1779 if (instr->HasSideEffects()) removed_side_effects_ =
true;
1787 GVNFlagSet previous_depends = *first_time_depends;
1788 GVNFlagSet previous_changes = *first_time_changes;
1789 first_time_depends->
Add(instr->DependsOnFlags());
1790 first_time_changes->Add(instr->ChangesFlags());
1791 if (!(previous_depends == *first_time_depends)) {
1792 TRACE_GVN_1(
"Updated first-time accumulated %s\n",
1795 if (!(previous_changes == *first_time_changes)) {
1796 TRACE_GVN_1(
"Updated first-time accumulated %s\n",
1805 bool HGlobalValueNumberer::AllowCodeMotion() {
1810 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1811 HBasicBlock* loop_header) {
1814 return AllowCodeMotion() && !instr->block()->IsDeoptimizing();
1818 GVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
1819 HBasicBlock* dominator, HBasicBlock* dominated) {
1821 for (
int i = 0; i < dominated->predecessors()->length(); ++i) {
1822 HBasicBlock* block = dominated->predecessors()->at(i);
1823 if (dominator->block_id() < block->block_id() &&
1824 block->block_id() < dominated->block_id() &&
1825 visited_on_paths_.Add(block->block_id())) {
1826 side_effects.
Add(block_side_effects_[block->block_id()]);
1827 if (block->IsLoopHeader()) {
1828 side_effects.Add(loop_side_effects_[block->block_id()]);
1830 side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock(
1834 return side_effects;
1862 *dominator =
block();
1864 if (result ==
NULL) {
1866 if (dominator_state !=
NULL) {
1869 *dominator = dominator_state->
block();
1870 result = dominator_state->next_dominated(zone);
1886 map_ = copy_map ? map->
Copy(zone) :
map;
1887 dominated_index_ = -1;
1889 if (dominators !=
NULL) {
1893 bool is_done() {
return dominated_index_ >= length_; }
1895 GvnBasicBlockState(GvnBasicBlockState* previous,
1898 HSideEffectMap* dominators,
1900 : previous_(previous), next_(
NULL) {
1901 Initialize(block, map, dominators,
true, zone);
1904 GvnBasicBlockState* next_dominated(Zone* zone) {
1906 if (dominated_index_ == length_ - 1) {
1914 }
else if (dominated_index_ < length_) {
1923 GvnBasicBlockState* push(Zone* zone,
1925 HSideEffectMap* dominators) {
1926 if (next_ ==
NULL) {
1928 new(zone) GvnBasicBlockState(
this, block,
map(),
dominators, zone);
1930 next_->Initialize(block,
map(), dominators,
true, zone);
1934 GvnBasicBlockState* pop() {
1935 GvnBasicBlockState* result = previous_;
1936 while (result !=
NULL && result->is_done()) {
1937 TRACE_GVN_2(
"Backtracking from block B%d to block b%d\n",
1938 block()->block_id(),
1940 result = result->previous_;
1945 GvnBasicBlockState* previous_;
1946 GvnBasicBlockState* next_;
1947 HBasicBlock* block_;
1949 HSideEffectMap dominators_;
1950 int dominated_index_;
1958 void HGlobalValueNumberer::AnalyzeGraph() {
1959 HBasicBlock* entry_block = graph_->entry_block();
1960 HValueMap* entry_map =
new(zone()) HValueMap(zone());
1961 GvnBasicBlockState* current =
1964 while (current !=
NULL) {
1965 HBasicBlock* block = current->block();
1966 HValueMap* map = current->map();
1967 HSideEffectMap* dominators = current->dominators();
1971 block->IsLoopHeader() ?
" (loop header)" :
"");
1974 if (block->IsLoopHeader()) {
1975 map->Kill(loop_side_effects_[block->block_id()]);
1979 HInstruction* instr = block->first();
1980 while (instr !=
NULL) {
1981 HInstruction* next = instr->next();
1983 if (!flags.IsEmpty()) {
1987 dominators->Store(flags, instr);
1992 ASSERT(!instr->HasObservableSideEffects());
1993 HValue* other = map->Lookup(instr);
1994 if (other !=
NULL) {
1995 ASSERT(instr->Equals(other) && other->Equals(instr));
1996 TRACE_GVN_4(
"Replacing value %d (%s) with value %d (%s)\n",
2001 if (instr->HasSideEffects()) removed_side_effects_ =
true;
2002 instr->DeleteAndReplaceWith(other);
2004 map->Add(instr, zone());
2009 HValue* other = dominators->at(i);
2012 if (instr->DependsOnFlags().Contains(depends_on_flag) &&
2014 TRACE_GVN_5(
"Side-effect #%d in %d (%s) is dominated by %d (%s)\n",
2020 instr->SetSideEffectDominator(changes_flag, other);
2027 HBasicBlock* dominator_block;
2028 GvnBasicBlockState* next =
2029 current->next_in_dominator_tree_traversal(zone(), &dominator_block);
2032 HBasicBlock* dominated = next->block();
2033 HValueMap* successor_map = next->map();
2034 HSideEffectMap* successor_dominators = next->dominators();
2041 if ((!successor_map->IsEmpty() || !successor_dominators->IsEmpty()) &&
2042 dominator_block->block_id() + 1 < dominated->block_id()) {
2043 visited_on_paths_.Clear();
2045 CollectSideEffectsOnPathsToDominatedBlock(dominator_block,
2047 successor_map->Kill(side_effects_on_all_paths);
2048 successor_dominators->Kill(side_effects_on_all_paths);
2060 worklist_(8, graph->zone()),
2061 in_worklist_(graph->GetMaximumValueID(), graph->zone()) { }
2067 void AddToWorklist(
HValue* current);
2068 void InferBasedOnInputs(
HValue* current);
2069 void AddDependantsToWorklist(
HValue* current);
2070 void InferBasedOnUses(
HValue* current);
2072 Zone* zone()
const {
return graph_->zone(); }
2075 ZoneList<HValue*> worklist_;
2076 BitVector in_worklist_;
2080 void HInferRepresentation::AddToWorklist(HValue* current) {
2081 if (current->representation().IsSpecialization())
return;
2083 if (in_worklist_.Contains(current->id()))
return;
2084 worklist_.Add(current, zone());
2085 in_worklist_.Add(current->id());
2093 void HInferRepresentation::InferBasedOnInputs(HValue* current) {
2094 Representation r = current->representation();
2095 if (r.IsSpecialization())
return;
2097 Representation inferred = current->InferredRepresentation();
2098 if (inferred.IsSpecialization()) {
2099 if (FLAG_trace_representation) {
2100 PrintF(
"Changing #%d representation %s -> %s based on inputs\n",
2103 inferred.Mnemonic());
2105 current->ChangeRepresentation(inferred);
2106 AddDependantsToWorklist(current);
2111 void HInferRepresentation::AddDependantsToWorklist(HValue* value) {
2112 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
2113 AddToWorklist(it.value());
2115 for (
int i = 0; i < value->OperandCount(); ++i) {
2116 AddToWorklist(value->OperandAt(i));
2125 void HInferRepresentation::InferBasedOnUses(HValue* value) {
2126 Representation r = value->representation();
2127 if (r.IsSpecialization() || value->HasNoUses())
return;
2129 Representation new_rep = TryChange(value);
2130 if (!new_rep.IsNone()) {
2131 if (!value->representation().Equals(new_rep)) {
2132 if (FLAG_trace_representation) {
2133 PrintF(
"Changing #%d representation %s -> %s based on uses\n",
2136 new_rep.Mnemonic());
2138 value->ChangeRepresentation(new_rep);
2139 AddDependantsToWorklist(value);
2145 Representation HInferRepresentation::TryChange(HValue* value) {
2149 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
2150 HValue* use = it.value();
2151 Representation rep = use->ObservedInputRepresentation(it.index());
2152 if (rep.IsNone())
continue;
2153 if (FLAG_trace_representation) {
2154 PrintF(
"%d %s is used by %d %s as %s\n",
2162 use_count[rep.kind()] += use->LoopWeight();
2167 int non_tagged_count = double_count + int32_count;
2170 if (value->IsPhi() && !value->block()->IsLoopHeader() && tagged_count > 0) {
2178 if (int32_count > 0 && value->IsConvertibleToInteger()) {
2188 void HInferRepresentation::Analyze() {
2189 HPhase phase(
"H_Infer representations", graph_);
2193 const ZoneList<HPhi*>* phi_list = graph_->phi_list();
2194 int phi_count = phi_list->length();
2195 ZoneList<BitVector*> connected_phis(phi_count, graph_->zone());
2196 for (
int i = 0; i < phi_count; ++i) {
2197 phi_list->at(i)->InitRealUses(i);
2198 BitVector* connected_set =
new(zone()) BitVector(phi_count, graph_->zone());
2199 connected_set->Add(i);
2200 connected_phis.Add(connected_set, zone());
2211 for (
int i = phi_count - 1; i >= 0; --i) {
2212 HPhi* phi = phi_list->at(i);
2213 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
2214 HValue* use = it.value();
2217 if (connected_phis[i]->UnionIsChanged(*connected_phis[
id]))
2228 for (
int i = 0; i < phi_count; ++i) {
2229 HPhi* phi = phi_list->at(i);
2230 bool cti = phi->AllOperandsConvertibleToInteger();
2233 for (BitVector::Iterator it(connected_phis.at(i));
2236 HPhi* phi = phi_list->at(it.Current());
2237 phi->set_is_convertible_to_integer(
false);
2238 phi->ResetInteger32Uses();
2244 for (
int i = 0; i < phi_count; ++i) {
2245 HPhi* phi = phi_list->at(i);
2246 for (BitVector::Iterator it(connected_phis.at(i));
2249 int index = it.Current();
2250 HPhi* it_use = phi_list->at(index);
2251 if (index != i) phi->AddNonPhiUsesFrom(it_use);
2256 for (
int i = 0; i < graph_->blocks()->length(); ++i) {
2257 HBasicBlock* block = graph_->blocks()->at(i);
2258 const ZoneList<HPhi*>* phis = block->phis();
2259 for (
int j = 0; j < phis->length(); ++j) {
2260 AddToWorklist(phis->at(j));
2263 HInstruction* current = block->first();
2264 while (current !=
NULL) {
2265 AddToWorklist(current);
2266 current = current->next();
2271 while (!worklist_.is_empty()) {
2272 HValue* current = worklist_.RemoveLast();
2273 in_worklist_.Remove(current->id());
2274 InferBasedOnInputs(current);
2275 InferBasedOnUses(current);
2281 HPhase phase(
"H_Inferring types",
this);
2287 for (
int i = from_inclusive; i <= to_inclusive; ++i) {
2291 for (
int j = 0; j < phis->length(); j++) {
2292 phis->
at(j)->UpdateInferredType();
2295 HInstruction* current = block->
first();
2296 while (current !=
NULL) {
2298 current = current->next();
2302 HBasicBlock* last_back_edge =
2306 i = last_back_edge->block_id();
2309 ZoneList<HValue*> worklist(block->
phis()->length(),
zone());
2310 for (
int j = 0; j < block->
phis()->length(); ++j) {
2313 InferTypes(&worklist);
2319 void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
2320 HValue* current = value;
2321 while (current !=
NULL) {
2322 if (visited->Contains(current->id()))
return;
2325 if (current->IsPhi()) {
2326 visited->Add(current->id());
2328 for (
int i = 0; i < phi->OperandCount(); ++i) {
2329 PropagateMinusZeroChecks(phi->OperandAt(i), visited);
2336 if (current->IsMul()) {
2338 mul->EnsureAndPropagateNotMinusZero(visited);
2339 PropagateMinusZeroChecks(mul->left(), visited);
2340 PropagateMinusZeroChecks(mul->right(), visited);
2341 }
else if (current->IsDiv()) {
2343 div->EnsureAndPropagateNotMinusZero(visited);
2344 PropagateMinusZeroChecks(div->left(), visited);
2345 PropagateMinusZeroChecks(div->right(), visited);
2348 current = current->EnsureAndPropagateNotMinusZero(visited);
2353 void HGraph::InsertRepresentationChangeForUse(HValue* value,
2356 Representation to) {
2359 HInstruction* next =
NULL;
2360 if (use_value->IsPhi()) {
2361 next = use_value->block()->predecessors()->at(use_index)->end();
2370 HInstruction* new_value =
NULL;
2372 bool deoptimize_on_undefined =
2374 if (value->IsConstant()) {
2377 new_value = is_truncating
2378 ? constant->CopyToTruncatedInt32(
zone())
2379 : constant->CopyToRepresentation(to,
zone());
2382 if (new_value ==
NULL) {
2383 new_value =
new(
zone()) HChange(value, to,
2384 is_truncating, deoptimize_on_undefined);
2387 new_value->InsertBefore(next);
2388 use_value->SetOperandAt(use_index, new_value);
2392 void HGraph::InsertRepresentationChangesForValue(HValue* value) {
2393 Representation r = value->representation();
2394 if (r.IsNone())
return;
2395 if (value->HasNoUses())
return;
2397 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
2398 HValue* use_value = it.value();
2399 int use_index = it.index();
2400 Representation req = use_value->RequiredInputRepresentation(use_index);
2401 if (req.IsNone() || req.Equals(r))
continue;
2402 InsertRepresentationChangeForUse(value, use_value, use_index, req);
2404 if (value->HasNoUses()) {
2405 ASSERT(value->IsConstant());
2406 value->DeleteAndReplaceWith(
NULL);
2411 if (value->IsForceRepresentation()) {
2418 HPhase phase(
"H_Representation changes",
this);
2425 for (
int i = 0; i <
phi_list()->length(); i++) {
2434 for (
int i = 0; i <
phi_list()->length(); i++) {
2444 for (
int i = 0; i < blocks_.length(); ++i) {
2447 for (
int j = 0; j < phis->length(); j++) {
2448 InsertRepresentationChangesForValue(phis->
at(j));
2453 while (current !=
NULL) {
2454 InsertRepresentationChangesForValue(current);
2455 current = current->
next();
2461 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(
HPhi* phi) {
2466 if (input->
IsPhi()) {
2467 RecursivelyMarkPhiDeoptimizeOnUndefined(
HPhi::cast(input));
2474 HPhase phase(
"H_MarkDeoptimizeOnUndefined",
this);
2481 for (
int i = 0; i <
phi_list()->length(); i++) {
2484 for (HUseIterator it(phi->
uses()); !it.Done(); it.Advance()) {
2486 RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
2497 for (
int i = 0; i < blocks_.length(); ++i) {
2500 current = current->next()) {
2501 if (current->IsChange()) {
2510 PropagateMinusZeroChecks(change->
value(), &visited);
2522 CompilationInfo* info,
2523 TypeFeedbackOracle* oracle,
2526 compilation_info_(info),
2528 call_context_(
NULL),
2529 return_handling_(return_handling),
2530 function_return_(
NULL),
2531 test_context_(
NULL),
2533 arguments_elements_(
NULL),
2534 outer_(owner->function_state()) {
2535 if (outer_ !=
NULL) {
2537 if (owner->ast_context()->
IsTest()) {
2545 test_context_ =
new TestContext(owner, cond, if_true, if_false);
2551 call_context_ = owner->ast_context();
2555 owner->set_function_state(
this);
2560 delete test_context_;
2561 owner_->set_function_state(outer_);
2570 outer_(owner->ast_context()),
2571 for_typeof_(
false) {
2572 owner->set_ast_context(
this);
2581 owner_->set_ast_context(outer_);
2588 (
owner()->environment()->length() == original_length_ &&
2596 (
owner()->environment()->length() == original_length_ + 1 &&
2610 owner()->
Bailout(
"bad value context for arguments value");
2622 ASSERT(!instr->IsControlInstruction());
2641 ASSERT(!instr->IsControlInstruction());
2643 return owner()->
Bailout(
"bad value context for arguments object value");
2654 return owner()->
Bailout(
"bad value context for arguments object value");
2672 ASSERT(!instr->IsControlInstruction());
2674 builder->AddInstruction(instr);
2678 builder->Push(instr);
2679 builder->AddSimulate(ast_id);
2693 empty_true->Goto(
if_true(),
owner()->function_state());
2699 void TestContext::BuildBranch(
HValue* value) {
2706 builder->
Bailout(
"arguments object value in a test context");
2711 ToBooleanStub::Types expected(builder->
oracle()->ToBooleanTypes(test_id));
2712 HBranch* test =
new(
zone()) HBranch(value, empty_true, empty_false, expected);
2715 empty_true->Goto(
if_true(),
owner()->function_state());
2722 #define CHECK_BAILOUT(call) \
2725 if (HasStackOverflow()) return; \
2729 #define CHECK_ALIVE(call) \
2732 if (HasStackOverflow() || current_block() == NULL) return; \
2737 if (FLAG_trace_bailout) {
2739 info()->shared_info()->DebugName()->
ToCString());
2740 PrintF(
"Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason);
2746 void HGraphBuilder::VisitForEffect(
Expression* expr) {
2753 ValueContext for_value(
this, flag);
2758 void HGraphBuilder::VisitForTypeOf(Expression* expr) {
2760 for_value.set_for_typeof(
true);
2766 void HGraphBuilder::VisitForControl(Expression* expr,
2767 HBasicBlock* true_block,
2768 HBasicBlock* false_block) {
2769 TestContext for_test(
this, expr, true_block, false_block);
2774 HValue* HGraphBuilder::VisitArgument(Expression* expr) {
2775 VisitForValue(expr);
2777 HValue* value =
Pop();
2783 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
2784 for (
int i = 0; i < arguments->length(); i++) {
2790 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
2791 for (
int i = 0; i < exprs->length(); ++i) {
2798 graph_ =
new(zone())
HGraph(info(), zone());
2802 HPhase phase(
"H_Block building");
2805 Scope* scope = info()->scope();
2807 Bailout(
"function with illegal redeclaration");
2811 Bailout(
"function calls eval");
2832 HBasicBlock* body_entry = CreateBasicBlock(initial_env);
2840 VisitVariableDeclaration(scope->
function());
2849 VisitStatements(info()->
function()->body());
2850 if (HasStackOverflow())
return NULL;
2864 graph()->Verify(
true);
2868 if (!
graph()->CheckConstPhiUses()) {
2869 Bailout(
"Unsupported phi use of const variable");
2873 if (!
graph()->CheckArgumentsPhiUses()) {
2874 Bailout(
"Unsupported phi use of arguments");
2880 if (
graph()->has_osr_loop_entry()) {
2882 for (
int j = 0; j < phis->length(); j++) {
2888 HInferRepresentation rep(
graph());
2899 HPhase phase(
"H_Global value numbering",
graph());
2900 HGlobalValueNumberer gvn(
graph(), info());
2901 bool removed_side_effects = gvn.Analyze();
2905 if (FLAG_smi_only_arrays && removed_side_effects) {
2906 removed_side_effects = gvn.Analyze();
2907 ASSERT(!removed_side_effects);
2911 if (FLAG_use_range) {
2912 HRangeAnalysis rangeAnalysis(
graph());
2913 rangeAnalysis.Analyze();
2918 HStackCheckEliminator sce(
graph());
2943 return static_cast<uint32_t
>(index_base_->
Hashcode() ^ length_->
Hashcode());
2951 bool is_sub =
false;
2953 if (check->
index()->IsAdd()) {
2955 if (index->
left()->IsConstant()) {
2957 index_base = index->
right();
2958 }
else if (index->
right()->IsConstant()) {
2960 index_base = index->
left();
2962 }
else if (check->
index()->IsSub()) {
2965 if (index->
left()->IsConstant()) {
2967 index_base = index->
right();
2968 }
else if (index->
right()->IsConstant()) {
2970 index_base = index->
left();
2979 index_base = check->
index();
2987 : index_base_(index_base),
2990 HValue* index_base_;
3048 if (new_offset > upper_offset_) {
3049 upper_offset_ = new_offset;
3050 }
else if (new_offset < lower_offset_) {
3051 lower_offset_ = new_offset;
3056 BuildOffsetAdd(&added_index_,
3057 &added_index_offset_,
3062 BuildOffsetAdd(&added_length_,
3063 &added_length_offset_,
3066 lower_offset_ - upper_offset_);
3073 RemoveZeroAdd(&added_index_, &added_index_offset_);
3074 RemoveZeroAdd(&added_length_, &added_length_offset_);
3085 lower_offset_(lower_offset),
3086 upper_offset_(upper_offset),
3089 added_index_offset_(
NULL),
3091 added_length_offset_(
NULL),
3092 added_length_(
NULL),
3093 next_in_bb_(next_in_bb),
3094 father_in_dt_(father_in_dt) { }
3105 HAdd* added_length_;
3109 void BuildOffsetAdd(
HAdd** add,
3123 (*add)->InsertBefore(
Check());
3126 (*constant)->DeleteAndReplaceWith(new_constant);
3128 *constant = new_constant;
3131 void RemoveZeroAdd(HAdd** add, HConstant** constant) {
3132 if (*add !=
NULL && (*constant)->Integer32Value() == 0) {
3134 (*constant)->DeleteAndReplaceWith(
NULL);
3140 static bool BoundsCheckKeyMatch(
void* key1,
void* key2) {
3141 BoundsCheckKey* k1 =
static_cast<BoundsCheckKey*
>(key1);
3142 BoundsCheckKey* k2 =
static_cast<BoundsCheckKey*
>(key2);
3143 return k1->IndexBase() == k2->IndexBase() && k1->Length() == k2->Length();
3174 BoundsCheckTable* table) {
3175 BoundsCheckBbData* bb_data_list =
NULL;
3177 for (HInstruction* i = bb->first(); i !=
NULL; i = i->next()) {
3178 if (!i->IsBoundsCheck())
continue;
3181 check->ReplaceAllUsesWith(check->index());
3183 if (!FLAG_array_bounds_checks_elimination)
continue;
3186 BoundsCheckKey* key =
3188 BoundsCheckBbData** data_p = table->LookupOrInsert(key,
zone());
3189 BoundsCheckBbData* data = *data_p;
3191 bb_data_list =
new(
zone()) BoundsCheckBbData(key,
3198 *data_p = bb_data_list;
3199 }
else if (data->OffsetIsCovered(offset)) {
3200 check->DeleteAndReplaceWith(
NULL);
3201 }
else if (data->BasicBlock() == bb) {
3202 data->CoverCheck(check, offset);
3204 int32_t new_lower_offset = offset < data->LowerOffset()
3206 : data->LowerOffset();
3207 int32_t new_upper_offset = offset > data->UpperOffset()
3209 : data->UpperOffset();
3210 bb_data_list =
new(
zone()) BoundsCheckBbData(key,
3217 table->Insert(key, bb_data_list,
zone());
3221 for (
int i = 0; i < bb->dominated_blocks()->length(); ++i) {
3225 for (BoundsCheckBbData* data = bb_data_list;
3227 data = data->NextInBasicBlock()) {
3228 data->RemoveZeroOperations();
3229 if (data->FatherInDominatorTree()) {
3230 table->Insert(data->Key(), data->FatherInDominatorTree(),
zone());
3232 table->Delete(data->Key());
3239 HPhase phase(
"H_Eliminate bounds checks",
this);
3252 if (index->IsAdd()) {
3255 if (add->
left()->IsConstant()) {
3256 subexpression = add->
right();
3258 }
else if (add->
right()->IsConstant()) {
3259 subexpression = add->
left();
3264 }
else if (index->IsSub()) {
3267 if (sub->left()->IsConstant()) {
3268 subexpression = sub->right();
3270 }
else if (sub->right()->IsConstant()) {
3271 subexpression = sub->left();
3282 if (value >= 1 << 30 || value < 0)
return;
3283 array_operation->
SetKey(subexpression);
3294 if (!FLAG_array_index_dehoisting)
return;
3296 HPhase phase(
"H_Dehoist index computations",
this);
3297 for (
int i = 0; i <
blocks()->length(); ++i) {
3300 instr = instr->next()) {
3302 if (instr->IsLoadKeyedFastElement()) {
3305 }
else if (instr->IsLoadKeyedFastDoubleElement()) {
3309 }
else if (instr->IsLoadKeyedSpecializedArrayElement()) {
3313 }
else if (instr->IsStoreKeyedFastElement()) {
3316 }
else if (instr->IsStoreKeyedFastDoubleElement()) {
3320 }
else if (instr->IsStoreKeyedSpecializedArrayElement()) {
3327 DehoistArrayIndex(array_instruction);
3346 void HGraphBuilder::AddPhi(
HPhi* instr) {
3352 void HGraphBuilder::PushAndAdd(HInstruction* instr) {
3358 template <
class Instruction>
3359 HInstruction* HGraphBuilder::PreProcessCall(Instruction* call) {
3360 int count = call->argument_count();
3361 ZoneList<HValue*> arguments(count, zone());
3362 for (
int i = 0; i < count; ++i) {
3363 arguments.Add(
Pop(), zone());
3366 while (!arguments.is_empty()) {
3367 AddInstruction(
new(zone()) HPushArgument(arguments.RemoveLast()));
3373 void HGraphBuilder::SetUpScope(Scope* scope) {
3374 HConstant* undefined_constant =
new(zone()) HConstant(
3379 HArgumentsObject*
object =
new(zone()) HArgumentsObject;
3388 HInstruction* parameter =
AddInstruction(
new(zone()) HParameter(i));
3397 for (
int i =
environment()->parameter_count() + 1;
3405 if (scope->arguments() !=
NULL) {
3406 if (!scope->arguments()->IsStackAllocated()) {
3407 return Bailout(
"context-allocated arguments");
3416 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
3417 for (
int i = 0; i < statements->length(); i++) {
3423 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
3430 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
3433 header->SetInitialEnvironment(entry_env);
3434 header->AttachLoopInformation();
3439 void HGraphBuilder::VisitBlock(
Block* stmt) {
3440 ASSERT(!HasStackOverflow());
3443 if (stmt->scope() !=
NULL) {
3444 return Bailout(
"ScopedBlock");
3446 BreakAndContinueInfo break_info(stmt);
3447 { BreakAndContinueScope push(&break_info,
this);
3450 HBasicBlock* break_block = break_info.break_block();
3451 if (break_block !=
NULL) {
3453 break_block->SetJoinId(stmt->ExitId());
3459 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
3460 ASSERT(!HasStackOverflow());
3463 VisitForEffect(stmt->expression());
3467 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
3468 ASSERT(!HasStackOverflow());
3474 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
3475 ASSERT(!HasStackOverflow());
3478 if (stmt->condition()->ToBooleanIsTrue()) {
3480 Visit(stmt->then_statement());
3481 }
else if (stmt->condition()->ToBooleanIsFalse()) {
3483 Visit(stmt->else_statement());
3487 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
3489 if (cond_true->HasPredecessor()) {
3490 cond_true->SetJoinId(stmt->ThenId());
3498 if (cond_false->HasPredecessor()) {
3499 cond_false->SetJoinId(stmt->ElseId());
3507 HBasicBlock* join =
CreateJoin(cond_true, cond_false, stmt->IfId());
3513 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get(
3514 BreakableStatement* stmt,
3518 BreakAndContinueScope* current =
this;
3519 while (current !=
NULL && current->info()->
target() != stmt) {
3520 *drop_extra += current->info()->drop_extra();
3521 current = current->next();
3525 if (type ==
BREAK) {
3526 *drop_extra += current->info()->drop_extra();
3529 HBasicBlock* block =
NULL;
3532 block = current->info()->break_block();
3533 if (block ==
NULL) {
3534 block = current->owner()->graph()->CreateBasicBlock();
3535 current->info()->set_break_block(block);
3540 block = current->info()->continue_block();
3541 if (block ==
NULL) {
3542 block = current->owner()->graph()->CreateBasicBlock();
3543 current->info()->set_continue_block(block);
3552 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
3553 ASSERT(!HasStackOverflow());
3557 HBasicBlock* continue_block =
break_scope()->Get(stmt->target(),
3566 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
3567 ASSERT(!HasStackOverflow());
3571 HBasicBlock* break_block =
break_scope()->Get(stmt->target(),
3580 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
3581 ASSERT(!HasStackOverflow());
3585 if (context ==
NULL) {
3594 if (context->IsTest()) {
3598 }
else if (context->IsEffect()) {
3602 ASSERT(context->IsValue());
3604 HValue* return_value =
Pop();
3606 HHasInstanceTypeAndBranch* typecheck =
3607 new(zone()) HHasInstanceTypeAndBranch(return_value,
3612 typecheck->SetSuccessorAt(0, if_spec_object);
3613 typecheck->SetSuccessorAt(1, not_spec_object);
3615 if_spec_object->AddLeaveInlined(return_value,
3618 not_spec_object->AddLeaveInlined(receiver,
3625 if (context->IsTest()) {
3627 VisitForControl(stmt->expression(),
3630 }
else if (context->IsEffect()) {
3634 ASSERT(context->IsValue());
3636 HValue* return_value =
Pop();
3646 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
3647 ASSERT(!HasStackOverflow());
3650 return Bailout(
"WithStatement");
3654 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
3655 ASSERT(!HasStackOverflow());
3660 const int kCaseClauseLimit = 128;
3661 ZoneList<CaseClause*>* clauses = stmt->cases();
3662 int clause_count = clauses->length();
3663 if (clause_count > kCaseClauseLimit) {
3664 return Bailout(
"SwitchStatement: too many clauses");
3671 HValue* tag_value =
Pop();
3677 for (
int i = 0; i < clause_count; ++i) {
3678 CaseClause* clause = clauses->at(i);
3679 if (clause->is_default())
continue;
3682 if (clause->label()->IsSmiLiteral()) {
3684 }
else if (clause->label()->IsStringLiteral()) {
3687 return Bailout(
"SwitchStatement: non-literal switch label");
3690 !clause->label()->IsStringLiteral()) ||
3692 !clause->label()->IsSmiLiteral())) {
3693 return Bailout(
"SwitchStatemnt: mixed label types are not supported");
3697 HUnaryControlInstruction* string_check =
NULL;
3698 HBasicBlock* not_string_block =
NULL;
3702 string_check =
new(zone()) HIsStringAndBranch(tag_value);
3706 string_check->SetSuccessorAt(0, first_test_block);
3707 string_check->SetSuccessorAt(1, not_string_block);
3715 for (
int i = 0; i < clause_count; ++i) {
3716 CaseClause* clause = clauses->at(i);
3717 if (clause->is_default()) {
3718 default_id = clause->EntryId();
3722 clause->RecordTypeFeedback(
oracle());
3727 HValue* label_value =
Pop();
3732 HControlInstruction* compare;
3735 if (!clause->IsSmiCompare()) {
3743 HCompareIDAndBranch* compare_ =
3744 new(zone()) HCompareIDAndBranch(tag_value,
3750 compare =
new(zone()) HStringCompareAndBranch(context, tag_value,
3755 compare->SetSuccessorAt(0, body_block);
3756 compare->SetSuccessorAt(1, next_test_block);
3766 if (not_string_block !=
NULL) {
3770 last_block =
CreateJoin(last_block, not_string_block, join_id);
3775 HBasicBlock* curr_test_block = first_test_block;
3776 HBasicBlock* fall_through_block =
NULL;
3778 BreakAndContinueInfo break_info(stmt);
3779 { BreakAndContinueScope push(&break_info,
this);
3780 for (
int i = 0; i < clause_count; ++i) {
3781 CaseClause* clause = clauses->at(i);
3785 HBasicBlock* normal_block =
NULL;
3786 if (clause->is_default()) {
3787 if (last_block !=
NULL) {
3788 normal_block = last_block;
3791 }
else if (!curr_test_block->end()->IsDeoptimize()) {
3792 normal_block = curr_test_block->end()->FirstSuccessor();
3793 curr_test_block = curr_test_block->end()->SecondSuccessor();
3797 if (normal_block ==
NULL) {
3798 if (fall_through_block ==
NULL) {
3800 if (clause->is_default()) {
3809 }
else if (fall_through_block ==
NULL) {
3814 HBasicBlock* join =
CreateJoin(fall_through_block,
3827 HBasicBlock* break_block = break_info.break_block();
3828 if (break_block ==
NULL) {
3833 if (fall_through_block !=
NULL) fall_through_block->Goto(break_block);
3834 if (last_block !=
NULL) last_block->Goto(break_block);
3835 break_block->SetJoinId(stmt->ExitId());
3841 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
3842 return statement->OsrEntryId() == info()->osr_ast_id();
3846 bool HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
3847 if (!HasOsrEntryAt(statement))
return false;
3852 HBranch* test =
new(zone()) HBranch(true_value, non_osr_entry, osr_entry);
3856 non_osr_entry->
Goto(loop_predecessor);
3859 int osr_entry_id = statement->OsrEntryId();
3862 ZoneList<HUnknownOSRValue*>* osr_values =
3863 new(zone()) ZoneList<HUnknownOSRValue*>(length, zone());
3865 for (
int i = 0; i < first_expression_index; ++i) {
3866 HUnknownOSRValue* osr_value =
new(zone()) HUnknownOSRValue;
3869 osr_values->Add(osr_value, zone());
3872 if (first_expression_index != length) {
3874 for (
int i = first_expression_index; i < length; ++i) {
3875 HUnknownOSRValue* osr_value =
new(zone()) HUnknownOSRValue;
3878 osr_values->Add(osr_value, zone());
3886 HContext* context =
new(zone()) HContext;
3890 loop_predecessor->SetJoinId(statement->EntryId());
3896 void HGraphBuilder::VisitLoopBody(IterationStatement* stmt,
3897 HBasicBlock* loop_entry,
3898 BreakAndContinueInfo* break_info) {
3899 BreakAndContinueScope push(break_info,
this);
3902 HStackCheck* stack_check =
3905 ASSERT(loop_entry->IsLoopHeader());
3906 loop_entry->loop_information()->set_stack_check(stack_check);
3911 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
3912 ASSERT(!HasStackOverflow());
3916 bool osr_entry = PreProcessOsrEntry(stmt);
3917 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
3922 BreakAndContinueInfo break_info(stmt);
3923 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
3924 HBasicBlock* body_exit =
3925 JoinContinue(stmt,
current_block(), break_info.continue_block());
3926 HBasicBlock* loop_successor =
NULL;
3927 if (body_exit !=
NULL && !stmt->cond()->ToBooleanIsTrue()) {
3933 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
3934 if (body_exit->HasPredecessor()) {
3935 body_exit->SetJoinId(stmt->BackEdgeId());
3939 if (loop_successor->HasPredecessor()) {
3940 loop_successor->SetJoinId(stmt->ExitId());
3942 loop_successor =
NULL;
3945 HBasicBlock* loop_exit = CreateLoop(stmt,
3949 break_info.break_block());
3954 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
3955 ASSERT(!HasStackOverflow());
3959 bool osr_entry = PreProcessOsrEntry(stmt);
3960 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
3967 HBasicBlock* loop_successor =
NULL;
3968 if (!stmt->cond()->ToBooleanIsTrue()) {
3971 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
3972 if (body_entry->HasPredecessor()) {
3973 body_entry->SetJoinId(stmt->BodyId());
3976 if (loop_successor->HasPredecessor()) {
3977 loop_successor->SetJoinId(stmt->ExitId());
3979 loop_successor =
NULL;
3983 BreakAndContinueInfo break_info(stmt);
3985 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
3987 HBasicBlock* body_exit =
3988 JoinContinue(stmt,
current_block(), break_info.continue_block());
3989 HBasicBlock* loop_exit = CreateLoop(stmt,
3993 break_info.break_block());
3998 void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
3999 ASSERT(!HasStackOverflow());
4002 if (stmt->init() !=
NULL) {
4006 bool osr_entry = PreProcessOsrEntry(stmt);
4007 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
4012 HBasicBlock* loop_successor =
NULL;
4013 if (stmt->cond() !=
NULL) {
4016 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
4017 if (body_entry->HasPredecessor()) {
4018 body_entry->SetJoinId(stmt->BodyId());
4021 if (loop_successor->HasPredecessor()) {
4022 loop_successor->SetJoinId(stmt->ExitId());
4024 loop_successor =
NULL;
4028 BreakAndContinueInfo break_info(stmt);
4030 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
4032 HBasicBlock* body_exit =
4033 JoinContinue(stmt,
current_block(), break_info.continue_block());
4035 if (stmt->next() !=
NULL && body_exit !=
NULL) {
4041 HBasicBlock* loop_exit = CreateLoop(stmt,
4045 break_info.break_block());
4050 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
4051 ASSERT(!HasStackOverflow());
4055 if (!FLAG_optimize_for_in) {
4056 return Bailout(
"ForInStatement optimization is disabled");
4059 if (!
oracle()->IsForInFastCase(stmt)) {
4060 return Bailout(
"ForInStatement is not fast case");
4063 if (!stmt->each()->IsVariableProxy() ||
4064 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
4065 return Bailout(
"ForInStatement with non-local each variable");
4068 Variable* each_var = stmt->each()->AsVariableProxy()->var();
4071 HValue* enumerable = Top();
4078 new(zone()) HForInCacheArray(
4084 new(zone()) HFixedArrayBaseLength(array));
4086 HInstruction* start_index =
AddInstruction(
new(zone()) HConstant(
4095 new(zone()) HForInCacheArray(
4102 bool osr_entry = PreProcessOsrEntry(stmt);
4103 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
4112 HCompareIDAndBranch* compare_index =
4113 new(zone()) HCompareIDAndBranch(index, limit, Token::LT);
4119 compare_index->SetSuccessorAt(0, loop_body);
4120 compare_index->SetSuccessorAt(1, loop_successor);
4129 new(zone()) HLoadKeyedFastElement(
4139 Bind(each_var, key);
4141 BreakAndContinueInfo break_info(stmt, 5);
4142 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
4144 HBasicBlock* body_exit =
4145 JoinContinue(stmt,
current_block(), break_info.continue_block());
4147 if (body_exit !=
NULL) {
4150 HValue* current_index =
Pop();
4155 PushAndAdd(new_index);
4159 HBasicBlock* loop_exit = CreateLoop(stmt,
4163 break_info.break_block());
4169 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
4170 ASSERT(!HasStackOverflow());
4173 return Bailout(
"TryCatchStatement");
4177 void HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
4178 ASSERT(!HasStackOverflow());
4181 return Bailout(
"TryFinallyStatement");
4185 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
4186 ASSERT(!HasStackOverflow());
4189 return Bailout(
"DebuggerStatement");
4193 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
4194 Code* unoptimized_code, FunctionLiteral* expr) {
4195 int start_position = expr->start_position();
4196 RelocIterator it(unoptimized_code);
4197 for (;!it.done(); it.next()) {
4198 RelocInfo* rinfo = it.rinfo();
4199 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT)
continue;
4200 Object* obj = rinfo->target_object();
4201 if (obj->IsSharedFunctionInfo()) {
4203 if (shared->start_position() == start_position) {
4204 return Handle<SharedFunctionInfo>(shared);
4209 return Handle<SharedFunctionInfo>();
4213 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
4214 ASSERT(!HasStackOverflow());
4217 Handle<SharedFunctionInfo> shared_info =
4218 SearchSharedFunctionInfo(info()->shared_info()->code(),
4220 if (shared_info.is_null()) {
4224 if (HasStackOverflow())
return;
4226 HFunctionLiteral* instr =
4227 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure());
4232 void HGraphBuilder::VisitSharedFunctionInfoLiteral(
4233 SharedFunctionInfoLiteral* expr) {
4234 ASSERT(!HasStackOverflow());
4237 return Bailout(
"SharedFunctionInfoLiteral");
4241 void HGraphBuilder::VisitConditional(Conditional* expr) {
4242 ASSERT(!HasStackOverflow());
4247 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
4251 if (cond_true->HasPredecessor()) {
4252 cond_true->SetJoinId(expr->ThenId());
4260 if (cond_false->HasPredecessor()) {
4261 cond_false->SetJoinId(expr->ElseId());
4269 if (!ast_context()->IsTest()) {
4270 HBasicBlock* join =
CreateJoin(cond_true, cond_false, expr->id());
4272 if (join !=
NULL && !ast_context()->IsEffect()) {
4279 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty(
4280 Variable* var, LookupResult* lookup,
bool is_store) {
4281 if (var->is_this() || !info()->has_global_object()) {
4284 Handle<GlobalObject> global(info()->global_object());
4285 global->Lookup(*var->name(), lookup);
4286 if (!lookup->IsFound() ||
4287 lookup->type() !=
NORMAL ||
4288 (is_store && lookup->IsReadOnly()) ||
4289 lookup->holder() != *global) {
4297 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
4298 ASSERT(var->IsContextSlot());
4300 int length = info()->scope()->ContextChainLength(var->scope());
4301 while (length-- > 0) {
4302 HInstruction* context_instruction =
new(zone()) HOuterContext(context);
4304 context = context_instruction;
4310 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
4311 ASSERT(!HasStackOverflow());
4314 Variable* variable = expr->var();
4315 switch (variable->location()) {
4318 return Bailout(
"reference to global harmony declared variable");
4322 Handle<Object> constant_value =
4323 isolate()->factory()->GlobalConstantFor(variable->name());
4324 if (!constant_value.is_null()) {
4330 LookupResult lookup(isolate());
4331 GlobalPropertyAccess type =
4332 LookupGlobalProperty(variable, &lookup,
false);
4334 if (type == kUseCell &&
4335 info()->global_object()->IsAccessCheckNeeded()) {
4339 if (type == kUseCell) {
4340 Handle<GlobalObject> global(info()->global_object());
4341 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
4342 HLoadGlobalCell* instr =
4343 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
4347 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
4349 HLoadGlobalGeneric* instr =
4350 new(zone()) HLoadGlobalGeneric(context,
4354 instr->set_position(expr->position());
4362 if (value ==
graph()->GetConstantHole()) {
4365 variable->mode() ==
LET);
4366 return Bailout(
"reference to uninitialized variable");
4372 HValue* context = BuildContextChainWalk(variable);
4373 HLoadContextSlot* instr =
new(zone()) HLoadContextSlot(context, variable);
4378 return Bailout(
"reference to a variable which requires dynamic lookup");
4383 void HGraphBuilder::VisitLiteral(Literal* expr) {
4384 ASSERT(!HasStackOverflow());
4393 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
4394 ASSERT(!HasStackOverflow());
4399 HRegExpLiteral* instr =
new(zone()) HRegExpLiteral(context,
4402 expr->literal_index());
4410 static bool IsFastLiteral(Handle<JSObject> boilerplate,
4412 int* max_properties,
4414 ASSERT(max_depth >= 0 && *max_properties >= 0);
4415 if (max_depth == 0)
return false;
4417 Handle<FixedArrayBase> elements(boilerplate->elements());
4418 if (elements->length() > 0 &&
4419 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) {
4420 if (boilerplate->HasFastDoubleElements()) {
4422 }
else if (boilerplate->HasFastObjectElements()) {
4424 int length = elements->length();
4425 for (
int i = 0; i < length; i++) {
4426 if ((*max_properties)-- == 0)
return false;
4427 Handle<Object> value(fast_elements->get(i));
4428 if (value->IsJSObject()) {
4430 if (!IsFastLiteral(value_object,
4444 Handle<FixedArray> properties(boilerplate->properties());
4445 if (properties->length() > 0) {
4448 int nof = boilerplate->map()->inobject_properties();
4449 for (
int i = 0; i < nof; i++) {
4450 if ((*max_properties)-- == 0)
return false;
4451 Handle<Object> value(boilerplate->InObjectPropertyAt(i));
4452 if (value->IsJSObject()) {
4454 if (!IsFastLiteral(value_object,
4464 *total_size += boilerplate->map()->instance_size();
4469 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
4470 ASSERT(!HasStackOverflow());
4475 HInstruction* literal;
4480 Handle<Object> boilerplate(closure->literals()->get(expr->literal_index()));
4481 if (boilerplate->IsJSObject() &&
4482 IsFastLiteral(Handle<JSObject>::cast(boilerplate),
4487 literal =
new(zone()) HFastLiteral(context,
4490 expr->literal_index(),
4493 literal =
new(zone()) HObjectLiteral(context,
4494 expr->constant_properties(),
4495 expr->fast_elements(),
4496 expr->literal_index(),
4498 expr->has_function());
4503 PushAndAdd(literal);
4505 expr->CalculateEmitStore(zone());
4507 for (
int i = 0; i < expr->properties()->length(); i++) {
4508 ObjectLiteral::Property*
property = expr->properties()->at(i);
4509 if (property->IsCompileTimeValue())
continue;
4511 Literal* key =
property->key();
4512 Expression* value =
property->value();
4514 switch (property->kind()) {
4519 if (key->handle()->IsSymbol()) {
4520 if (property->emit_store()) {
4521 property->RecordTypeFeedback(
oracle());
4523 HValue* value =
Pop();
4524 HInstruction* store;
4525 CHECK_ALIVE(store = BuildStoreNamed(literal, value, property));
4527 if (store->HasObservableSideEffects())
AddSimulate(key->id());
4537 return Bailout(
"Object literal with complex property");
4542 if (expr->has_function()) {
4548 HToFastProperties* result =
new(zone()) HToFastProperties(
Pop());
4557 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
4558 ASSERT(!HasStackOverflow());
4561 ZoneList<Expression*>* subexprs = expr->values();
4562 int length = subexprs->length();
4564 HInstruction* literal;
4566 Handle<FixedArray> literals(
environment()->closure()->literals());
4567 Handle<Object> raw_boilerplate(literals->get(expr->literal_index()));
4569 if (raw_boilerplate->IsUndefined()) {
4571 isolate(), literals, expr->constant_elements());
4572 if (raw_boilerplate.is_null()) {
4573 return Bailout(
"array boilerplate creation failed");
4575 literals->set(expr->literal_index(), *raw_boilerplate);
4577 isolate()->heap()->fixed_cow_array_map()) {
4578 isolate()->counters()->cow_arrays_created_runtime()->Increment();
4589 if (IsFastLiteral(boilerplate,
4593 literal =
new(zone()) HFastLiteral(context,
4596 expr->literal_index(),
4599 literal =
new(zone()) HArrayLiteral(context,
4602 expr->literal_index(),
4608 PushAndAdd(literal);
4610 HLoadElements* elements =
NULL;
4612 for (
int i = 0; i < length; i++) {
4613 Expression* subexpr = subexprs->at(i);
4619 HValue* value =
Pop();
4622 elements =
new(zone()) HLoadElements(literal);
4629 switch (boilerplate_elements_kind) {
4641 boilerplate_elements_kind));
4645 AddInstruction(
new(zone()) HStoreKeyedFastDoubleElement(elements,
4661 static bool ComputeLoadStoreField(Handle<Map> type,
4662 Handle<String>
name,
4663 LookupResult* lookup,
4665 type->LookupInDescriptors(
NULL, *name, lookup);
4666 if (!lookup->IsFound())
return false;
4667 if (lookup->type() ==
FIELD)
return true;
4669 (type->unused_property_fields() > 0);
4673 static int ComputeLoadStoreFieldIndex(Handle<Map> type,
4674 Handle<String> name,
4675 LookupResult* lookup) {
4677 if (lookup->type() ==
FIELD) {
4678 return lookup->GetLocalFieldIndexFromMap(*type);
4680 Map* transition = lookup->GetTransitionMapFromMap(*type);
4681 return transition->PropertyIndexFor(*name) - type->inobject_properties();
4686 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue*
object,
4687 Handle<String> name,
4690 LookupResult* lookup,
4691 bool smi_and_map_check) {
4692 ASSERT(lookup->IsFound());
4693 if (smi_and_map_check) {
4701 if (!lookup->IsProperty()) {
4702 Object* proto = type->prototype();
4704 LookupResult proto_result(isolate());
4705 proto->Lookup(*name, &proto_result);
4706 if (proto_result.IsProperty()) {
4708 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) {
4709 Bailout(
"improper object on prototype chain for store");
4713 proto = proto_result.holder();
4716 while (proto->GetPrototype()->IsJSObject()) proto = proto->GetPrototype();
4717 ASSERT(proto->GetPrototype()->IsNull());
4719 ASSERT(proto->IsJSObject());
4725 int index = ComputeLoadStoreFieldIndex(type, name, lookup);
4726 bool is_in_object = index < 0;
4731 offset += type->instance_size();
4735 HStoreNamedField* instr =
4736 new(zone()) HStoreNamedField(
object, name, value, is_in_object, offset);
4738 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
4739 instr->set_transition(transition);
4742 instr->SetGVNFlag(kChangesMaps);
4748 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue*
object,
4749 Handle<String> name,
4752 return new(zone()) HStoreNamedGeneric(
4757 function_strict_mode_flag());
4761 HInstruction* HGraphBuilder::BuildStoreNamed(HValue*
object,
4763 ObjectLiteral::Property* prop) {
4764 Literal* key = prop->key()->AsLiteral();
4768 LookupResult lookup(isolate());
4769 Handle<Map> type = prop->GetReceiverType();
4770 bool is_monomorphic = prop->IsMonomorphic() &&
4771 ComputeLoadStoreField(type, name, &lookup,
true);
4773 return is_monomorphic
4774 ? BuildStoreNamedField(
object, name, value, type, &lookup,
4776 : BuildStoreNamedGeneric(object, name, value);
4780 HInstruction* HGraphBuilder::BuildStoreNamed(HValue*
object,
4783 Property* prop = (expr->AsProperty() !=
NULL)
4784 ? expr->AsProperty()
4785 : expr->AsAssignment()->target()->AsProperty();
4786 Literal* key = prop->key()->AsLiteral();
4790 LookupResult lookup(isolate());
4791 SmallMapList* types = expr->GetReceiverTypes();
4792 bool is_monomorphic = expr->IsMonomorphic() &&
4793 ComputeLoadStoreField(types->first(),
name, &lookup,
true);
4795 return is_monomorphic
4796 ? BuildStoreNamedField(
object, name, value, types->first(), &lookup,
4798 : BuildStoreNamedGeneric(
object, name, value);
4802 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
4804 SmallMapList* types,
4805 Handle<String> name) {
4807 int previous_field_offset = 0;
4808 bool previous_field_is_in_object =
false;
4809 bool is_monomorphic_field =
true;
4811 LookupResult lookup(isolate());
4812 for (
int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
4814 if (ComputeLoadStoreField(map, name, &lookup,
false)) {
4815 int index = ComputeLoadStoreFieldIndex(map, name, &lookup);
4816 bool is_in_object = index < 0;
4821 offset += map->instance_size();
4826 previous_field_offset = offset;
4827 previous_field_is_in_object = is_in_object;
4828 }
else if (is_monomorphic_field) {
4829 is_monomorphic_field = (offset == previous_field_offset) &&
4830 (is_in_object == previous_field_is_in_object);
4838 HInstruction* instr;
4839 if (count == types->length() && is_monomorphic_field) {
4841 instr = BuildLoadNamedField(
object, expr, map, &lookup,
false);
4844 instr =
new(zone()) HLoadNamedFieldPolymorphic(context,
4851 instr->set_position(expr->position());
4856 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
4859 SmallMapList* types,
4860 Handle<String> name) {
4865 HBasicBlock* join =
NULL;
4866 for (
int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
4867 Handle<Map> map = types->at(i);
4868 LookupResult lookup(isolate());
4869 if (ComputeLoadStoreField(map, name, &lookup,
true)) {
4877 HCompareMap* compare =
4878 new(zone()) HCompareMap(
object, map, if_true, if_false);
4882 HInstruction* instr;
4884 BuildStoreNamedField(
object, name, value, map, &lookup,
false));
4885 instr->set_position(expr->position());
4888 if (!ast_context()->IsEffect())
Push(value);
4898 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4901 HInstruction* instr = BuildStoreNamedGeneric(
object, name, value);
4902 instr->set_position(expr->position());
4906 if (!ast_context()->IsEffect())
Push(value);
4912 if (instr->HasObservableSideEffects()) {
4926 join->SetJoinId(expr->id());
4928 if (!ast_context()->IsEffect())
return ast_context()->
ReturnValue(
Pop());
4932 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
4933 Property* prop = expr->target()->AsProperty();
4935 expr->RecordTypeFeedback(
oracle(), zone());
4938 HValue* value =
NULL;
4939 HInstruction* instr =
NULL;
4941 if (prop->key()->IsPropertyName()) {
4945 HValue*
object =
Pop();
4947 Literal* key = prop->key()->AsLiteral();
4951 SmallMapList* types = expr->GetReceiverTypes();
4952 if (expr->IsMonomorphic()) {
4953 CHECK_ALIVE(instr = BuildStoreNamed(
object, value, expr));
4955 }
else if (types !=
NULL && types->length() > 1) {
4956 HandlePolymorphicStoreNamedField(expr,
object, value, types, name);
4960 instr = BuildStoreNamedGeneric(
object, name, value);
4968 HValue* key =
Pop();
4969 HValue*
object =
Pop();
4970 bool has_side_effects =
false;
4971 HandleKeyedElementAccess(
object, key, value, expr, expr->AssignmentId(),
4976 ASSERT(has_side_effects);
4981 instr->set_position(expr->position());
4983 if (instr->HasObservableSideEffects())
AddSimulate(expr->AssignmentId());
4991 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
4995 LookupResult lookup(isolate());
4996 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup,
true);
4997 if (type == kUseCell) {
4998 Handle<GlobalObject> global(info()->global_object());
4999 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
5000 HInstruction* instr =
5001 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails());
5002 instr->set_position(position);
5004 if (instr->HasObservableSideEffects())
AddSimulate(ast_id);
5007 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
5009 HStoreGlobalGeneric* instr =
5010 new(zone()) HStoreGlobalGeneric(context,
5014 function_strict_mode_flag());
5015 instr->set_position(position);
5017 ASSERT(instr->HasObservableSideEffects());
5018 if (instr->HasObservableSideEffects())
AddSimulate(ast_id);
5023 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
5024 Expression* target = expr->target();
5025 VariableProxy* proxy = target->AsVariableProxy();
5026 Property* prop = target->AsProperty();
5031 BinaryOperation* operation = expr->binary_operation();
5033 if (proxy !=
NULL) {
5034 Variable* var = proxy->var();
5035 if (var->mode() ==
LET) {
5036 return Bailout(
"unsupported let compound assignment");
5041 switch (var->location()) {
5043 HandleGlobalVariableAssignment(var,
5046 expr->AssignmentId());
5051 if (var->mode() ==
CONST) {
5052 return Bailout(
"unsupported const compound assignment");
5061 if (info()->scope()->arguments() !=
NULL) {
5065 int count = info()->scope()->num_parameters();
5066 for (
int i = 0; i < count; ++i) {
5067 if (var == info()->scope()->parameter(i)) {
5069 "assignment to parameter, function uses arguments object");
5076 switch (var->mode()) {
5090 HValue* context = BuildContextChainWalk(var);
5091 HStoreContextSlot* instr =
5092 new(zone()) HStoreContextSlot(context, var->index(), mode, Top());
5094 if (instr->HasObservableSideEffects()) {
5101 return Bailout(
"compound assignment to lookup slot");
5105 }
else if (prop !=
NULL) {
5106 prop->RecordTypeFeedback(
oracle(), zone());
5108 if (prop->key()->IsPropertyName()) {
5111 HValue* obj = Top();
5113 HInstruction* load =
NULL;
5114 if (prop->IsMonomorphic()) {
5115 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
5116 Handle<Map> map = prop->GetReceiverTypes()->first();
5117 load = BuildLoadNamed(obj, prop, map, name);
5119 load = BuildLoadNamedGeneric(obj, prop);
5122 if (load->HasObservableSideEffects())
AddSimulate(expr->CompoundLoadId());
5125 HValue* right =
Pop();
5126 HValue* left =
Pop();
5128 HInstruction* instr = BuildBinaryOperation(operation, left, right);
5130 if (instr->HasObservableSideEffects())
AddSimulate(operation->id());
5132 HInstruction* store;
5133 CHECK_ALIVE(store = BuildStoreNamed(obj, instr, prop));
5138 if (store->HasObservableSideEffects())
AddSimulate(expr->AssignmentId());
5148 bool has_side_effects =
false;
5149 HValue* load = HandleKeyedElementAccess(
5150 obj, key,
NULL, prop, expr->CompoundLoadId(), RelocInfo::kNoPosition,
5154 if (has_side_effects)
AddSimulate(expr->CompoundLoadId());
5158 HValue* right =
Pop();
5159 HValue* left =
Pop();
5161 HInstruction* instr = BuildBinaryOperation(operation, left, right);
5163 if (instr->HasObservableSideEffects())
AddSimulate(operation->id());
5165 expr->RecordTypeFeedback(
oracle(), zone());
5166 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
5167 RelocInfo::kNoPosition,
5174 ASSERT(has_side_effects);
5180 return Bailout(
"invalid lhs in compound assignment");
5185 void HGraphBuilder::VisitAssignment(Assignment* expr) {
5186 ASSERT(!HasStackOverflow());
5189 VariableProxy* proxy = expr->target()->AsVariableProxy();
5190 Property* prop = expr->target()->AsProperty();
5193 if (expr->is_compound()) {
5194 HandleCompoundAssignment(expr);
5199 HandlePropertyAssignment(expr);
5200 }
else if (proxy !=
NULL) {
5201 Variable* var = proxy->var();
5203 if (var->mode() ==
CONST) {
5204 if (expr->op() != Token::INIT_CONST) {
5209 if (var->IsStackAllocated()) {
5216 if (expr->op() != Token::INIT_CONST_HARMONY) {
5217 return Bailout(
"non-initializer assignment to const");
5221 if (proxy->IsArguments())
return Bailout(
"assignment to arguments");
5224 switch (var->location()) {
5227 HandleGlobalVariableAssignment(var,
5230 expr->AssignmentId());
5237 if (var->mode() ==
LET && expr->op() == Token::ASSIGN) {
5239 if (env_value ==
graph()->GetConstantHole()) {
5240 return Bailout(
"assignment to let variable before initialization");
5247 HValue* value =
Pop();
5256 if (info()->scope()->arguments() !=
NULL) {
5259 int count = info()->scope()->num_parameters();
5260 for (
int i = 0; i < count; ++i) {
5261 if (var == info()->scope()->parameter(i)) {
5262 return Bailout(
"assignment to parameter in arguments object");
5269 if (expr->op() == Token::ASSIGN) {
5270 switch (var->mode()) {
5283 }
else if (expr->op() == Token::INIT_VAR ||
5284 expr->op() == Token::INIT_LET ||
5285 expr->op() == Token::INIT_CONST_HARMONY) {
5288 ASSERT(expr->op() == Token::INIT_CONST);
5293 HValue* context = BuildContextChainWalk(var);
5294 HStoreContextSlot* instr =
new(zone()) HStoreContextSlot(
5295 context, var->index(), mode, Top());
5297 if (instr->HasObservableSideEffects()) {
5304 return Bailout(
"assignment to LOOKUP variable");
5307 return Bailout(
"invalid left-hand side in assignment");
5312 void HGraphBuilder::VisitThrow(Throw* expr) {
5313 ASSERT(!HasStackOverflow());
5319 ASSERT(ast_context()->IsEffect());
5324 HThrow* instr =
new(zone()) HThrow(context, value);
5325 instr->set_position(expr->position());
5333 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue*
object,
5336 LookupResult* lookup,
5337 bool smi_and_map_check) {
5338 if (smi_and_map_check) {
5343 int index = lookup->GetLocalFieldIndexFromMap(*type);
5347 int offset = (index *
kPointerSize) + type->instance_size();
5348 return new(zone()) HLoadNamedField(
object,
true, offset);
5352 return new(zone()) HLoadNamedField(
object,
false, offset);
5357 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
5359 if (expr->IsUninitialized() && !FLAG_always_opt) {
5363 ASSERT(expr->key()->IsPropertyName());
5364 Handle<Object> name = expr->key()->AsLiteral()->handle();
5366 return new(zone()) HLoadNamedGeneric(context, obj, name);
5370 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
5373 Handle<String> name) {
5374 LookupResult lookup(isolate());
5375 map->LookupInDescriptors(
NULL, *name, &lookup);
5376 if (lookup.IsFound() && lookup.type() ==
FIELD) {
5377 return BuildLoadNamedField(obj,
5385 Handle<JSFunction>
function(lookup.GetConstantFunctionFromMap(*map));
5388 return BuildLoadNamedGeneric(obj, expr);
5393 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue*
object,
5396 return new(zone()) HLoadKeyedGeneric(context,
object, key);
5400 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
5401 HValue* external_elements,
5402 HValue* checked_key,
5408 switch (elements_kind) {
5419 if (!val->representation().IsInteger32()) {
5442 return new(zone()) HStoreKeyedSpecializedArrayElement(
5443 external_elements, checked_key, val, elements_kind);
5446 return new(zone()) HLoadKeyedSpecializedArrayElement(
5447 external_elements, checked_key, elements_kind);
5452 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
5453 HValue* checked_key,
5459 switch (elements_kind) {
5462 return new(zone()) HStoreKeyedFastDoubleElement(
5463 elements, checked_key, val);
5471 return new(zone()) HStoreKeyedFastElement(
5472 elements, checked_key, val, elements_kind);
5483 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key, mode);
5485 return new(zone()) HLoadKeyedFastElement(elements, checked_key,
5491 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue*
object,
5497 HInstruction* mapcheck =
5498 AddInstruction(
new(zone()) HCheckMaps(
object, map, zone(), dependency));
5508 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
5510 bool fast_smi_only_elements = map->has_fast_smi_elements();
5511 bool fast_elements = map->has_fast_object_elements();
5512 HInstruction* elements =
AddInstruction(
new(zone()) HLoadElements(
object));
5513 if (is_store && (fast_elements || fast_smi_only_elements)) {
5514 HCheckMaps* check_cow_map =
new(zone()) HCheckMaps(
5515 elements, isolate()->factory()->fixed_array_map(), zone());
5516 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
5519 HInstruction* length =
NULL;
5520 HInstruction* checked_key =
NULL;
5521 if (map->has_external_array_elements()) {
5522 length =
AddInstruction(
new(zone()) HFixedArrayBaseLength(elements));
5523 checked_key =
AddInstruction(
new(zone()) HBoundsCheck(key, length));
5524 HLoadExternalArrayPointer* external_elements =
5525 new(zone()) HLoadExternalArrayPointer(elements);
5527 return BuildExternalArrayElementAccess(external_elements, checked_key,
5528 val, map->elements_kind(), is_store);
5530 ASSERT(fast_smi_only_elements ||
5532 map->has_fast_double_elements());
5534 length =
AddInstruction(
new(zone()) HJSArrayLength(
object, mapcheck,
5537 length =
AddInstruction(
new(zone()) HFixedArrayBaseLength(elements));
5539 checked_key =
AddInstruction(
new(zone()) HBoundsCheck(key, length));
5540 return BuildFastElementAccess(elements, checked_key, val,
5541 map->elements_kind(), is_store);
5545 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue*
object,
5552 bool* has_side_effects) {
5553 *has_side_effects =
false;
5555 SmallMapList* maps = prop->GetReceiverTypes();
5556 bool todo_external_array =
false;
5559 bool type_todo[kNumElementTypes];
5560 for (
int i = 0; i < kNumElementTypes; ++i) {
5561 type_todo[i] =
false;
5568 for (
int i = 0; i < maps->length(); ++i) {
5569 Handle<Map> map = maps->at(i);
5573 possible_transitioned_maps.Add(map);
5577 for (
int i = 0; i < maps->length(); ++i) {
5578 Handle<Map> map = maps->at(i);
5579 Handle<Map> transitioned_map =
5580 map->FindTransitionedMap(&possible_transitioned_maps);
5581 transition_target.Add(transitioned_map);
5584 int num_untransitionable_maps = 0;
5585 Handle<Map> untransitionable_map;
5586 HTransitionElementsKind* transition =
NULL;
5587 for (
int i = 0; i < maps->length(); ++i) {
5588 Handle<Map> map = maps->at(i);
5590 if (!transition_target.at(i).is_null()) {
5592 map->elements_kind(),
5593 transition_target.at(i)->elements_kind()));
5594 transition =
new(zone()) HTransitionElementsKind(
5595 object, map, transition_target.at(i));
5598 type_todo[map->elements_kind()] =
true;
5600 todo_external_array =
true;
5602 num_untransitionable_maps++;
5603 untransitionable_map = map;
5609 if (num_untransitionable_maps == 1) {
5610 HInstruction* instr =
NULL;
5611 if (untransitionable_map->has_slow_elements_kind()) {
5612 instr =
AddInstruction(is_store ? BuildStoreKeyedGeneric(
object, key, val)
5613 : BuildLoadKeyedGeneric(
object, key));
5616 object, key, val, transition, untransitionable_map, is_store));
5618 *has_side_effects |= instr->HasObservableSideEffects();
5619 instr->set_position(position);
5620 return is_store ?
NULL : instr;
5626 HInstruction* elements_kind_instr =
5628 HCompareConstantEqAndBranch* elements_kind_branch =
NULL;
5629 HInstruction* elements =
AddInstruction(
new(zone()) HLoadElements(
object));
5630 HLoadExternalArrayPointer* external_elements =
NULL;
5631 HInstruction* checked_key =
NULL;
5648 && todo_external_array) {
5649 HInstruction* length =
5651 checked_key =
AddInstruction(
new(zone()) HBoundsCheck(key, length));
5652 external_elements =
new(zone()) HLoadExternalArrayPointer(elements);
5655 if (type_todo[elements_kind]) {
5658 elements_kind_branch =
new(zone()) HCompareConstantEqAndBranch(
5659 elements_kind_instr, elements_kind, Token::EQ_STRICT);
5660 elements_kind_branch->SetSuccessorAt(0, if_true);
5661 elements_kind_branch->SetSuccessorAt(1, if_false);
5665 HInstruction* access;
5669 elements, isolate()->factory()->fixed_array_map(),
5670 zone(), elements_kind_branch));
5682 HHasInstanceTypeAndBranch* typecheck =
5683 new(zone()) HHasInstanceTypeAndBranch(
object,
JS_ARRAY_TYPE);
5684 typecheck->SetSuccessorAt(0, if_jsarray);
5685 typecheck->SetSuccessorAt(1, if_fastobject);
5689 HInstruction* length;
5690 length =
AddInstruction(
new(zone()) HJSArrayLength(
object, typecheck,
5692 checked_key =
AddInstruction(
new(zone()) HBoundsCheck(key, length));
5694 elements, checked_key, val, elements_kind, is_store));
5699 *has_side_effects |= access->HasObservableSideEffects();
5700 if (position != -1) {
5701 access->set_position(position);
5703 if_jsarray->Goto(join);
5706 length =
AddInstruction(
new(zone()) HFixedArrayBaseLength(elements));
5707 checked_key =
AddInstruction(
new(zone()) HBoundsCheck(key, length));
5709 elements, checked_key, val, elements_kind, is_store));
5712 access =
AddInstruction(BuildStoreKeyedGeneric(
object, key, val));
5718 external_elements, checked_key, val, elements_kind, is_store));
5720 *has_side_effects |= access->HasObservableSideEffects();
5721 access->set_position(position);
5732 join->SetJoinId(ast_id);
5734 return is_store ?
NULL :
Pop();
5738 HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj,
5745 bool* has_side_effects) {
5746 ASSERT(!expr->IsPropertyName());
5747 HInstruction* instr =
NULL;
5748 if (expr->IsMonomorphic()) {
5749 Handle<Map> map = expr->GetMonomorphicReceiverType();
5750 if (map->has_slow_elements_kind()) {
5751 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
5752 : BuildLoadKeyedGeneric(obj, key);
5755 instr = BuildMonomorphicElementAccess(obj, key, val,
NULL, map, is_store);
5757 }
else if (expr->GetReceiverTypes() !=
NULL &&
5758 !expr->GetReceiverTypes()->is_empty()) {
5759 return HandlePolymorphicElementAccess(
5760 obj, key, val, expr, ast_id, position, is_store, has_side_effects);
5763 instr = BuildStoreKeyedGeneric(obj, key, val);
5765 instr = BuildLoadKeyedGeneric(obj, key);
5768 instr->set_position(position);
5770 *has_side_effects = instr->HasObservableSideEffects();
5775 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue*
object,
5779 return new(zone()) HStoreKeyedGeneric(
5784 function_strict_mode_flag());
5788 void HGraphBuilder::EnsureArgumentsArePushedForAccess() {
5799 HInstruction* insert_after = entry;
5800 for (
int i = 0; i < arguments_values->length(); i++) {
5801 HValue* argument = arguments_values->at(i);
5802 HInstruction* push_argument =
new(zone()) HPushArgument(argument);
5803 push_argument->InsertAfter(insert_after);
5804 insert_after = push_argument;
5807 HArgumentsElements* arguments_elements =
5808 new(zone()) HArgumentsElements(
true);
5810 arguments_elements->InsertAfter(insert_after);
5815 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
5816 VariableProxy* proxy = expr->obj()->AsVariableProxy();
5817 if (proxy ==
NULL)
return false;
5818 if (!proxy->var()->IsStackAllocated())
return false;
5823 HInstruction* result =
NULL;
5824 if (expr->key()->IsPropertyName()) {
5825 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
5826 if (!name->IsEqualTo(
CStrVector(
"length")))
return false;
5830 new(zone()) HArgumentsElements(
false));
5831 result =
new(zone()) HArgumentsLength(elements);
5836 result =
new(zone()) HConstant(
5842 VisitForValue(expr->key());
5844 HValue* key =
Pop();
5848 new(zone()) HArgumentsElements(
false));
5850 new(zone()) HArgumentsLength(elements));
5851 HInstruction* checked_key =
5853 result =
new(zone()) HAccessArgumentsAt(elements, length, checked_key);
5855 EnsureArgumentsArePushedForAccess();
5864 HInstruction* checked_key =
5866 result =
new(zone()) HAccessArgumentsAt(elements, length, checked_key);
5874 void HGraphBuilder::VisitProperty(Property* expr) {
5875 ASSERT(!HasStackOverflow());
5878 expr->RecordTypeFeedback(
oracle(), zone());
5880 if (TryArgumentsAccess(expr))
return;
5884 HInstruction* instr =
NULL;
5885 if (expr->AsProperty()->IsArrayLength()) {
5886 HValue* array =
Pop();
5888 HInstruction* mapcheck =
5890 instr =
new(zone()) HJSArrayLength(array, mapcheck);
5891 }
else if (expr->IsStringLength()) {
5892 HValue*
string =
Pop();
5895 instr =
new(zone()) HStringLength(
string);
5896 }
else if (expr->IsStringAccess()) {
5898 HValue* index =
Pop();
5899 HValue*
string =
Pop();
5901 HStringCharCodeAt* char_code =
5902 BuildStringCharCodeAt(context,
string, index);
5904 instr =
new(zone()) HStringCharFromCode(context, char_code);
5906 }
else if (expr->IsFunctionPrototype()) {
5907 HValue*
function =
Pop();
5909 instr =
new(zone()) HLoadFunctionPrototype(
function);
5911 }
else if (expr->key()->IsPropertyName()) {
5912 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
5913 SmallMapList* types = expr->GetReceiverTypes();
5915 HValue* obj =
Pop();
5916 if (expr->IsMonomorphic()) {
5917 instr = BuildLoadNamed(obj, expr, types->first(),
name);
5918 }
else if (types !=
NULL && types->length() > 1) {
5920 HandlePolymorphicLoadNamedField(expr, obj, types, name);
5923 instr = BuildLoadNamedGeneric(obj, expr);
5929 HValue* key =
Pop();
5930 HValue* obj =
Pop();
5932 bool has_side_effects =
false;
5933 HValue* load = HandleKeyedElementAccess(
5934 obj, key,
NULL, expr, expr->id(), expr->position(),
5937 if (has_side_effects) {
5948 instr->set_position(expr->position());
5953 void HGraphBuilder::AddCheckConstantFunction(Call* expr,
5955 Handle<Map> receiver_map,
5956 bool smi_and_map_check) {
5960 if (smi_and_map_check) {
5965 if (!expr->holder().is_null()) {
5979 ast_length_(ast_length),
5980 src_length_(src_length) { }
5995 static int CompareHotness(
void const* a,
void const* b) {
5996 FunctionSorter
const* function1 =
reinterpret_cast<FunctionSorter const*
>(a);
5997 FunctionSorter
const* function2 =
reinterpret_cast<FunctionSorter const*
>(b);
5998 int diff = function1->ticks() - function2->ticks();
5999 if (diff != 0)
return -diff;
6000 diff = function1->ast_length() - function2->ast_length();
6001 if (diff != 0)
return diff;
6002 return function1->src_length() - function2->src_length();
6006 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
6008 SmallMapList* types,
6009 Handle<String> name) {
6013 int argument_count = expr->arguments()->length() + 1;
6014 HBasicBlock* join =
NULL;
6015 FunctionSorter order[kMaxCallPolymorphism];
6016 int ordered_functions = 0;
6018 i < types->length() && ordered_functions < kMaxCallPolymorphism;
6020 Handle<Map> map = types->at(i);
6021 if (expr->ComputeTarget(map, name)) {
6022 order[ordered_functions++] =
6024 expr->target()->shared()->profiler_ticks(),
6025 InliningAstSize(expr->target()),
6026 expr->target()->shared()->SourceSize());
6030 qsort(reinterpret_cast<void*>(&order[0]),
6035 for (
int fn = 0; fn < ordered_functions; ++fn) {
6036 int i = order[fn].index();
6037 Handle<Map> map = types->at(i);
6045 HCompareMap* compare =
6046 new(zone()) HCompareMap(receiver, map, if_true, if_false);
6050 expr->ComputeTarget(map, name);
6051 AddCheckConstantFunction(expr, receiver, map,
false);
6052 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
6053 Handle<JSFunction> caller = info()->closure();
6054 SmartArrayPointer<char> caller_name =
6055 caller->shared()->DebugName()->ToCString();
6056 PrintF(
"Trying to inline the polymorphic call to %s from %s\n",
6060 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
6063 if (HasStackOverflow())
return;
6065 HCallConstantFunction* call =
6066 new(zone()) HCallConstantFunction(expr->target(), argument_count);
6067 call->set_position(expr->position());
6068 PreProcessCall(call);
6070 if (!ast_context()->IsEffect())
Push(call);
6080 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
6084 HCallNamed* call =
new(zone()) HCallNamed(context, name, argument_count);
6085 call->set_position(expr->position());
6086 PreProcessCall(call);
6090 if (!ast_context()->IsEffect())
Push(call);
6101 if (join->HasPredecessor()) {
6103 join->SetJoinId(expr->id());
6111 void HGraphBuilder::TraceInline(Handle<JSFunction> target,
6112 Handle<JSFunction> caller,
6113 const char* reason) {
6114 if (FLAG_trace_inlining) {
6115 SmartArrayPointer<char> target_name =
6116 target->shared()->DebugName()->ToCString();
6117 SmartArrayPointer<char> caller_name =
6118 caller->shared()->DebugName()->ToCString();
6119 if (reason ==
NULL) {
6120 PrintF(
"Inlined %s called from %s.\n", *target_name, *caller_name);
6122 PrintF(
"Did not inline %s called from %s (%s).\n",
6123 *target_name, *caller_name, reason);
6129 static const int kNotInlinable = 1000000000;
6132 int HGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
6133 if (!FLAG_use_inlining)
return kNotInlinable;
6137 Handle<JSFunction> caller = info()->closure();
6138 Handle<SharedFunctionInfo> target_shared(target->shared());
6142 if (target_shared->SourceSize() >
6143 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
6144 TraceInline(target, caller,
"target text too big");
6145 return kNotInlinable;
6149 if (!target->IsInlineable()) {
6150 TraceInline(target, caller,
"target not inlineable");
6151 return kNotInlinable;
6153 if (target_shared->dont_inline() || target_shared->dont_optimize()) {
6154 TraceInline(target, caller,
"target contains unsupported syntax [early]");
6155 return kNotInlinable;
6158 int nodes_added = target_shared->ast_node_count();
6163 bool HGraphBuilder::TryInline(
CallKind call_kind,
6164 Handle<JSFunction> target,
6165 ZoneList<Expression*>* arguments,
6170 int nodes_added = InliningAstSize(target);
6171 if (nodes_added == kNotInlinable)
return false;
6173 Handle<JSFunction> caller = info()->closure();
6175 if (nodes_added >
Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
6176 TraceInline(target, caller,
"target AST is too large [early]");
6180 Handle<SharedFunctionInfo> target_shared(target->shared());
6182 #if !defined(V8_TARGET_ARCH_IA32)
6184 CompilationInfo* outer_info = info();
6185 if (target->context() != outer_info->closure()->context() ||
6186 outer_info->scope()->contains_with() ||
6187 outer_info->scope()->num_heap_slots() > 0) {
6188 TraceInline(target, caller,
"target requires context change");
6196 int current_level = 1;
6197 while (env->outer() !=
NULL) {
6199 TraceInline(target, caller,
"inline depth limit reached");
6211 state = state->outer()) {
6212 if (state->compilation_info()->closure()->shared() == *target_shared) {
6213 TraceInline(target, caller,
"target is recursive");
6219 if (inlined_count_ >
Min(FLAG_max_inlined_nodes_cumulative,
6220 kUnlimitedMaxInlinedNodesCumulative)) {
6221 TraceInline(target, caller,
"cumulative AST node limit reached");
6226 CompilationInfo target_info(target);
6229 if (target_info.isolate()->has_pending_exception()) {
6232 target_shared->DisableOptimization();
6234 TraceInline(target, caller,
"parse failure");
6238 if (target_info.scope()->num_heap_slots() > 0) {
6239 TraceInline(target, caller,
"target has context-allocated variables");
6242 FunctionLiteral*
function = target_info.function();
6246 nodes_added =
function->ast_node_count();
6247 if (nodes_added >
Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
6248 TraceInline(target, caller,
"target AST is too large [late]");
6251 AstProperties::Flags*
flags(function->flags());
6253 TraceInline(target, caller,
"target contains unsupported syntax [late]");
6260 if (function->scope()->arguments() !=
NULL) {
6261 if (!FLAG_inline_arguments) {
6262 TraceInline(target, caller,
"target uses arguments object");
6266 if (!function->scope()->arguments()->IsStackAllocated()) {
6269 "target uses non-stackallocated arguments object");
6275 ZoneList<Declaration*>* decls = target_info.scope()->declarations();
6276 int decl_count = decls->length();
6277 for (
int i = 0; i < decl_count; ++i) {
6278 if (!decls->at(i)->IsInlineable()) {
6279 TraceInline(target, caller,
"target has non-trivial declaration");
6286 if (!target_shared->has_deoptimization_support()) {
6289 target_info.EnableDeoptimizationSupport();
6291 TraceInline(target, caller,
"could not generate deoptimization info");
6297 Handle<ScopeInfo> target_scope_info =
6299 target_shared->set_scope_info(*target_scope_info);
6301 target_shared->EnableDeoptimizationSupport(*target_info.code());
6313 ASSERT(target_shared->has_deoptimization_support());
6314 TypeFeedbackOracle target_oracle(
6315 Handle<Code>(target_shared->code()),
6316 Handle<Context>(target->context()->global_context()),
6322 this, &target_info, &target_oracle, return_handling);
6325 HEnvironment* inner_env =
6327 arguments->length(),
6332 #ifdef V8_TARGET_ARCH_IA32
6338 HConstant* context =
6339 new(zone()) HConstant(Handle<Context>(target->context()),
6342 inner_env->BindContext(context);
6348 ZoneList<HValue*>* arguments_values =
NULL;
6352 if (function->scope()->arguments() !=
NULL) {
6353 HEnvironment* arguments_env = inner_env->arguments_environment();
6354 int arguments_count = arguments_env->parameter_count();
6355 arguments_values =
new(zone()) ZoneList<HValue*>(arguments_count, zone());
6356 for (
int i = 0; i < arguments_count; i++) {
6357 arguments_values->Add(arguments_env->Lookup(i), zone());
6361 HEnterInlined* enter_inlined =
6362 new(zone()) HEnterInlined(target,
6363 arguments->length(),
6367 function->scope()->arguments(),
6373 if (function->scope()->arguments() !=
NULL) {
6374 ASSERT(function->scope()->arguments()->IsStackAllocated());
6375 inner_env->Bind(function->scope()->arguments(),
6381 VisitStatements(function->body());
6382 if (HasStackOverflow()) {
6385 TraceInline(target, caller,
"inline graph construction failed");
6386 target_shared->DisableOptimization();
6387 inline_bailout_ =
true;
6388 delete target_state;
6393 inlined_count_ += nodes_added;
6395 TraceInline(target, caller,
NULL);
6401 if (call_context()->IsValue()) {
6409 }
else if (call_context()->IsEffect()) {
6413 ASSERT(call_context()->IsTest());
6416 ? inlined_test_context()->
if_true()
6417 : inlined_test_context()->
if_false();
6423 if (inlined_test_context() !=
NULL) {
6424 HBasicBlock* if_true = inlined_test_context()->
if_true();
6425 HBasicBlock* if_false = inlined_test_context()->
if_false();
6428 ASSERT(ast_context() == inlined_test_context());
6429 ClearInlinedTestContext();
6430 delete target_state;
6433 if (if_true->HasPredecessor()) {
6434 if_true->SetJoinId(ast_id);
6438 if (if_false->HasPredecessor()) {
6439 if_false->SetJoinId(ast_id);
6446 }
else if (function_return()->HasPredecessor()) {
6452 delete target_state;
6457 bool HGraphBuilder::TryInlineCall(Call* expr,
bool drop_extra) {
6460 CallKind call_kind = (expr->expression()->AsProperty() ==
NULL)
6464 return TryInline(call_kind,
6474 bool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) {
6485 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr,
bool drop_extra) {
6486 if (!expr->target()->shared()->HasBuiltinFunctionId())
return false;
6496 if (expr->arguments()->length() == 1) {
6497 HValue* argument =
Pop();
6500 HUnaryMathOperation* op =
6501 new(zone()) HUnaryMathOperation(context, argument,
id);
6502 op->set_position(expr->position());
6503 if (drop_extra) Drop(1);
6516 bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr,
6518 Handle<Map> receiver_map,
6522 if (!expr->target()->shared()->HasBuiltinFunctionId())
return false;
6524 int argument_count = expr->arguments()->length() + 1;
6526 case kStringCharCodeAt:
6528 if (argument_count == 2 && check_type ==
STRING_CHECK) {
6529 HValue* index =
Pop();
6530 HValue*
string =
Pop();
6532 ASSERT(!expr->holder().is_null());
6536 HStringCharCodeAt* char_code =
6537 BuildStringCharCodeAt(context,
string, index);
6538 if (
id == kStringCharCodeAt) {
6543 HStringCharFromCode* result =
6544 new(zone()) HStringCharFromCode(context, char_code);
6558 AddCheckConstantFunction(expr, receiver, receiver_map,
true);
6559 HValue* argument =
Pop();
6562 HUnaryMathOperation* op =
6563 new(zone()) HUnaryMathOperation(context, argument,
id);
6564 op->set_position(expr->position());
6571 AddCheckConstantFunction(expr, receiver, receiver_map,
true);
6572 HValue* right =
Pop();
6573 HValue* left =
Pop();
6576 HInstruction* result =
NULL;
6578 if (right->IsConstant() &&
HConstant::cast(right)->HasDoubleValue()) {
6580 if (exponent == 0.5) {
6582 new(zone()) HUnaryMathOperation(context, left,
kMathPowHalf);
6583 }
else if (exponent == -0.5) {
6584 HConstant* double_one =
6588 HUnaryMathOperation* square_root =
6589 new(zone()) HUnaryMathOperation(context, left,
kMathPowHalf);
6593 ASSERT(!square_root->HasObservableSideEffects());
6594 result =
new(zone()) HDiv(context, double_one, square_root);
6595 }
else if (exponent == 2.0) {
6596 result =
new(zone()) HMul(context, left, left);
6598 }
else if (right->IsConstant() &&
6601 result =
new(zone()) HMul(context, left, left);
6604 if (result ==
NULL) {
6605 result =
new(zone()) HPower(left, right);
6613 AddCheckConstantFunction(expr, receiver, receiver_map,
true);
6616 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
6618 HRandom* result =
new(zone()) HRandom(global_object);
6626 AddCheckConstantFunction(expr, receiver, receiver_map,
true);
6627 HValue* right =
Pop();
6628 HValue* left =
Pop();
6631 HValue* left_operand = left;
6632 HValue* right_operand = right;
6635 if (!left->representation().IsInteger32() ||
6636 !right->representation().IsInteger32()) {
6637 if (!left->representation().IsDouble()) {
6638 HChange* left_convert =
new(zone()) HChange(
6646 if (!right->representation().IsDouble()) {
6647 HChange* right_convert =
new(zone()) HChange(
6657 ASSERT(left_operand->representation().Equals(
6658 right_operand->representation()));
6659 ASSERT(!left_operand->representation().IsTagged());
6661 Token::Value op = (
id == kMathMin) ? Token::LT : Token::GT;
6663 HCompareIDAndBranch* compare =
6664 new(zone()) HCompareIDAndBranch(left_operand, right_operand, op);
6665 compare->SetInputRepresentation(left_operand->representation());
6670 compare->SetSuccessorAt(0, return_left);
6671 compare->SetSuccessorAt(1, return_right);
6680 if (left_operand->representation().IsDouble()) {
6682 HCompareIDAndBranch* compare_nan =
new(zone()) HCompareIDAndBranch(
6684 compare_nan->SetInputRepresentation(left_operand->representation());
6687 compare_nan->SetSuccessorAt(0, left_is_number);
6688 compare_nan->SetSuccessorAt(1, left_is_nan);
6694 return_right =
CreateJoin(left_is_number, left_is_nan, expr->id());
6699 HBasicBlock* join =
CreateJoin(return_left, return_right, expr->id());
6713 bool HGraphBuilder::TryCallApply(Call* expr) {
6714 Expression* callee = expr->expression();
6715 Property* prop = callee->AsProperty();
6721 Handle<Map> function_map = expr->GetReceiverTypes()->first();
6723 !expr->target()->shared()->HasBuiltinFunctionId() ||
6724 expr->target()->shared()->builtin_function_id() != kFunctionApply) {
6728 if (info()->scope()->arguments() ==
NULL)
return false;
6730 ZoneList<Expression*>* args = expr->arguments();
6731 if (args->length() != 2)
return false;
6733 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
6734 if (arg_two ==
NULL || !arg_two->var()->IsStackAllocated())
return false;
6739 VisitForValue(prop->obj());
6741 HValue*
function = Top();
6742 AddCheckConstantFunction(expr,
function, function_map,
true);
6745 VisitForValue(args->at(0));
6747 HValue* receiver =
Pop();
6751 new(zone()) HArgumentsElements(
false));
6752 HInstruction* length =
6754 HValue* wrapped_receiver =
6756 HInstruction* result =
6757 new(zone()) HApplyArguments(
function,
6761 result->set_position(expr->position());
6769 HValue* wrapped_receiver =
6771 PushAndAdd(
new(zone()) HPushArgument(wrapped_receiver));
6776 for (
int i = 1; i < arguments_env->parameter_count(); i++) {
6777 PushAndAdd(
new(zone()) HPushArgument(arguments_env->Lookup(i)));
6780 HInvokeFunction* call =
new(zone()) HInvokeFunction(
6784 Drop(parameter_count);
6785 call->set_position(expr->position());
6792 void HGraphBuilder::VisitCall(Call* expr) {
6793 ASSERT(!HasStackOverflow());
6796 Expression* callee = expr->expression();
6797 int argument_count = expr->arguments()->length() + 1;
6798 HInstruction* call =
NULL;
6800 Property* prop = callee->AsProperty();
6802 if (!prop->key()->IsPropertyName()) {
6808 HValue* key =
Pop();
6809 HValue* receiver =
Pop();
6813 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
6816 call =
new(zone()) HCallKeyed(context, key, argument_count);
6817 call->set_position(expr->position());
6818 Drop(argument_count + 1);
6825 if (TryCallApply(expr))
return;
6830 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
6832 SmallMapList* types = expr->GetReceiverTypes();
6836 if (expr->IsMonomorphic()) {
6837 Handle<Map> receiver_map = (types ==
NULL || types->is_empty())
6838 ? Handle<Map>::null()
6840 if (TryInlineBuiltinMethodCall(expr,
6843 expr->check_type())) {
6844 if (FLAG_trace_inlining) {
6845 PrintF(
"Inlining builtin ");
6846 expr->target()->ShortPrint();
6858 call = PreProcessCall(
6859 new(zone()) HCallNamed(context, name, argument_count));
6861 AddCheckConstantFunction(expr, receiver, receiver_map,
true);
6863 if (TryInlineCall(expr))
return;
6864 call = PreProcessCall(
6865 new(zone()) HCallConstantFunction(expr->target(),
6868 }
else if (types !=
NULL && types->length() > 1) {
6870 HandlePolymorphicCallNamed(expr, receiver, types, name);
6875 call = PreProcessCall(
6876 new(zone()) HCallNamed(context, name, argument_count));
6881 VariableProxy* proxy = expr->expression()->AsVariableProxy();
6882 bool global_call = proxy !=
NULL && proxy->var()->IsUnallocated();
6884 if (proxy !=
NULL && proxy->var()->is_possibly_eval()) {
6885 return Bailout(
"possible direct call to eval");
6889 Variable* var = proxy->var();
6890 bool known_global_function =
false;
6894 LookupResult lookup(isolate());
6895 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup,
false);
6896 if (type == kUseCell &&
6897 !info()->global_object()->IsAccessCheckNeeded()) {
6898 Handle<GlobalObject> global(info()->global_object());
6899 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
6901 if (known_global_function) {
6905 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
6906 PushAndAdd(global_object);
6910 HValue*
function =
Pop();
6911 AddInstruction(
new(zone()) HCheckFunction(
function, expr->target()));
6914 HGlobalReceiver* global_receiver =
6915 new(zone()) HGlobalReceiver(global_object);
6917 const int receiver_index = argument_count - 1;
6923 if (TryInlineBuiltinFunctionCall(expr,
false)) {
6924 if (FLAG_trace_inlining) {
6925 PrintF(
"Inlining builtin ");
6926 expr->target()->ShortPrint();
6931 if (TryInlineCall(expr))
return;
6933 if (expr->target().is_identical_to(info()->closure())) {
6937 call = PreProcessCall(
new(zone()) HCallKnownGlobal(expr->target(),
6941 HGlobalObject* receiver =
new(zone()) HGlobalObject(context);
6943 PushAndAdd(
new(zone()) HPushArgument(receiver));
6944 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
6946 call =
new(zone()) HCallGlobal(context, var->name(), argument_count);
6947 Drop(argument_count);
6950 }
else if (expr->IsMonomorphic()) {
6954 HValue*
function = Top();
6956 HGlobalObject* global =
new(zone()) HGlobalObject(context);
6958 HGlobalReceiver* receiver =
new(zone()) HGlobalReceiver(global);
6959 PushAndAdd(receiver);
6961 AddInstruction(
new(zone()) HCheckFunction(
function, expr->target()));
6963 if (TryInlineBuiltinFunctionCall(expr,
true)) {
6964 if (FLAG_trace_inlining) {
6965 PrintF(
"Inlining builtin ");
6966 expr->target()->ShortPrint();
6972 if (TryInlineCall(expr,
true)) {
6975 call = PreProcessCall(
6976 new(zone()) HInvokeFunction(context,
6985 HValue*
function = Top();
6987 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
6989 HGlobalReceiver* receiver =
new(zone()) HGlobalReceiver(global_object);
6991 PushAndAdd(
new(zone()) HPushArgument(receiver));
6992 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
6994 call =
new(zone()) HCallFunction(context,
function, argument_count);
6995 Drop(argument_count + 1);
6999 call->set_position(expr->position());
7005 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
7006 return constructor->has_initial_map() &&
7012 void HGraphBuilder::VisitCallNew(CallNew* expr) {
7013 ASSERT(!HasStackOverflow());
7016 expr->RecordTypeFeedback(
oracle());
7017 int argument_count = expr->arguments()->length() + 1;
7020 if (FLAG_inline_construct &&
7021 expr->IsMonomorphic() &&
7022 IsAllocationInlineable(expr->target())) {
7026 HValue*
function = Top();
7028 Handle<JSFunction> constructor = expr->target();
7030 new(zone()) HCheckFunction(
function, constructor));
7034 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) {
7035 constructor->shared()->CompleteInobjectSlackTracking();
7039 HInstruction* receiver =
new(zone()) HAllocateObject(context, constructor);
7041 const int receiver_index = argument_count - 1;
7046 if (TryInlineConstruct(expr, receiver))
return;
7052 receiver->DeleteAndReplaceWith(
NULL);
7053 check->DeleteAndReplaceWith(
NULL);
7055 HInstruction* call = PreProcessCall(
7056 new(zone()) HCallNew(context,
function, argument_count));
7057 call->set_position(expr->position());
7062 HValue* constructor =
NULL;
7063 CHECK_ALIVE(constructor = VisitArgument(expr->expression()));
7064 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7065 HInstruction* call =
7066 new(zone()) HCallNew(context, constructor, argument_count);
7067 Drop(argument_count);
7068 call->set_position(expr->position());
7078 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
7079 &HGraphBuilder::Generate##Name,
7081 const HGraphBuilder::InlineFunctionGenerator
7082 HGraphBuilder::kInlineFunctionGenerators[] = {
7086 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
7089 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
7090 ASSERT(!HasStackOverflow());
7093 if (expr->is_jsruntime()) {
7094 return Bailout(
"call to a JavaScript runtime function");
7097 const Runtime::Function*
function = expr->function();
7100 ASSERT(expr->name()->length() > 0);
7101 ASSERT(expr->name()->Get(0) ==
'_');
7103 int lookup_index =
static_cast<int>(
function->function_id) -
7105 ASSERT(lookup_index >= 0);
7106 ASSERT(static_cast<size_t>(lookup_index) <
7108 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
7111 (this->*generator)(expr);
7114 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7117 Handle<String> name = expr->name();
7118 int argument_count = expr->arguments()->length();
7119 HCallRuntime* call =
7120 new(zone()) HCallRuntime(context, name,
function, argument_count);
7121 call->set_position(RelocInfo::kNoPosition);
7122 Drop(argument_count);
7128 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
7129 ASSERT(!HasStackOverflow());
7132 switch (expr->op()) {
7133 case Token::DELETE:
return VisitDelete(expr);
7135 case Token::TYPEOF:
return VisitTypeof(expr);
7138 case Token::BIT_NOT:
return VisitBitNot(expr);
7139 case Token::NOT:
return VisitNot(expr);
7144 void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
7145 Property* prop = expr->expression()->AsProperty();
7146 VariableProxy* proxy = expr->expression()->AsVariableProxy();
7150 HValue* key =
Pop();
7151 HValue* obj =
Pop();
7153 HDeleteProperty* instr =
new(zone()) HDeleteProperty(context, obj, key);
7155 }
else if (proxy !=
NULL) {
7156 Variable* var = proxy->var();
7157 if (var->IsUnallocated()) {
7158 Bailout(
"delete with global variable");
7159 }
else if (var->IsStackAllocated() || var->IsContextSlot()) {
7163 HValue* value = var->is_this()
7168 Bailout(
"delete with non-global variable");
7179 void HGraphBuilder::VisitVoid(UnaryOperation* expr) {
7185 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) {
7187 HValue* value =
Pop();
7189 HInstruction* instr =
new(zone()) HTypeof(context, value);
7194 void HGraphBuilder::VisitAdd(UnaryOperation* expr) {
7196 HValue* value =
Pop();
7198 HInstruction* instr =
7199 new(zone()) HMul(context, value, graph_->
GetConstant1());
7204 void HGraphBuilder::VisitSub(UnaryOperation* expr) {
7206 HValue* value =
Pop();
7208 HInstruction* instr =
7210 TypeInfo info =
oracle()->UnaryType(expr);
7211 if (info.IsUninitialized()) {
7216 Representation rep = ToRepresentation(info);
7217 TraceRepresentation(expr->op(), info, instr, rep);
7218 instr->AssumeRepresentation(rep);
7223 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
7225 HValue* value =
Pop();
7226 TypeInfo info =
oracle()->UnaryType(expr);
7227 if (info.IsUninitialized()) {
7231 HInstruction* instr =
new(zone()) HBitNot(value);
7236 void HGraphBuilder::VisitNot(UnaryOperation* expr) {
7237 if (ast_context()->IsTest()) {
7239 VisitForControl(expr->expression(),
7240 context->if_false(),
7241 context->if_true());
7246 VisitForEffect(expr->expression());
7250 ASSERT(ast_context()->IsValue());
7257 if (materialize_false->HasPredecessor()) {
7258 materialize_false->SetJoinId(expr->MaterializeFalseId());
7262 materialize_false =
NULL;
7265 if (materialize_true->HasPredecessor()) {
7266 materialize_true->SetJoinId(expr->MaterializeTrueId());
7270 materialize_true =
NULL;
7274 CreateJoin(materialize_false, materialize_true, expr->id());
7280 HInstruction* HGraphBuilder::BuildIncrement(
bool returns_original_input,
7281 CountOperation* expr) {
7283 TypeInfo info =
oracle()->IncrementType(expr);
7284 Representation rep = ToRepresentation(info);
7285 if (rep.IsTagged()) {
7289 if (returns_original_input) {
7294 HInstruction* number_input =
new(zone()) HForceRepresentation(
Pop(), rep);
7302 HConstant* delta = (expr->op() == Token::INC)
7306 HInstruction* instr =
new(zone()) HAdd(context, Top(), delta);
7307 TraceRepresentation(expr->op(), info, instr, rep);
7308 instr->AssumeRepresentation(rep);
7314 void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
7315 ASSERT(!HasStackOverflow());
7318 Expression* target = expr->expression();
7319 VariableProxy* proxy = target->AsVariableProxy();
7320 Property* prop = target->AsProperty();
7321 if (proxy ==
NULL && prop ==
NULL) {
7322 return Bailout(
"invalid lhs in count operation");
7328 bool returns_original_input =
7329 expr->is_postfix() && !ast_context()->
IsEffect();
7330 HValue* input =
NULL;
7331 HValue* after =
NULL;
7333 if (proxy !=
NULL) {
7334 Variable* var = proxy->var();
7335 if (var->mode() ==
CONST) {
7336 return Bailout(
"unsupported count operation with const");
7342 after = BuildIncrement(returns_original_input, expr);
7343 input = returns_original_input ? Top() :
Pop();
7346 switch (var->location()) {
7348 HandleGlobalVariableAssignment(var,
7351 expr->AssignmentId());
7363 if (info()->scope()->arguments() !=
NULL) {
7367 int count = info()->scope()->num_parameters();
7368 for (
int i = 0; i < count; ++i) {
7369 if (var == info()->scope()->parameter(i)) {
7370 return Bailout(
"assignment to parameter in arguments object");
7375 HValue* context = BuildContextChainWalk(var);
7379 HStoreContextSlot* instr =
7380 new(zone()) HStoreContextSlot(context, var->index(), mode, after);
7382 if (instr->HasObservableSideEffects()) {
7389 return Bailout(
"lookup variable in count operation");
7395 prop->RecordTypeFeedback(
oracle(), zone());
7397 if (prop->key()->IsPropertyName()) {
7402 HValue* obj = Top();
7404 HInstruction* load =
NULL;
7405 if (prop->IsMonomorphic()) {
7406 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
7407 Handle<Map> map = prop->GetReceiverTypes()->first();
7408 load = BuildLoadNamed(obj, prop, map, name);
7410 load = BuildLoadNamedGeneric(obj, prop);
7413 if (load->HasObservableSideEffects())
AddSimulate(expr->CountId());
7415 after = BuildIncrement(returns_original_input, expr);
7418 HInstruction* store;
7419 CHECK_ALIVE(store = BuildStoreNamed(obj, after, prop));
7427 if (store->HasObservableSideEffects())
AddSimulate(expr->AssignmentId());
7438 bool has_side_effects =
false;
7439 HValue* load = HandleKeyedElementAccess(
7440 obj, key,
NULL, prop, expr->CountId(), RelocInfo::kNoPosition,
7444 if (has_side_effects)
AddSimulate(expr->CountId());
7446 after = BuildIncrement(returns_original_input, expr);
7449 expr->RecordTypeFeedback(
oracle(), zone());
7450 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(),
7451 RelocInfo::kNoPosition,
7461 ASSERT(has_side_effects);
7466 Drop(returns_original_input ? 2 : 1);
7467 return ast_context()->
ReturnValue(expr->is_postfix() ? input : after);
7471 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context,
7476 HStringLength* length =
new(zone()) HStringLength(
string);
7478 HInstruction* checked_index =
7480 return new(zone()) HStringCharCodeAt(context,
string, checked_index);
7484 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
7488 TypeInfo info =
oracle()->BinaryType(expr);
7489 if (info.IsUninitialized()) {
7494 HInstruction* instr =
NULL;
7495 switch (expr->op()) {
7497 if (info.IsString()) {
7502 instr =
new(zone()) HStringAdd(context, left, right);
7519 case Token::BIT_XOR:
7520 case Token::BIT_AND:
7545 Representation rep = ToRepresentation(info);
7547 if (instr->IsBitwiseBinaryOperation()) {
7549 InitializeObservedInputRepresentation(rep);
7552 TraceRepresentation(expr->op(), info, instr, rep);
7553 instr->AssumeRepresentation(rep);
7559 static bool IsClassOfTest(CompareOperation* expr) {
7560 if (expr->op() != Token::EQ_STRICT)
return false;
7561 CallRuntime* call = expr->left()->AsCallRuntime();
7562 if (call ==
NULL)
return false;
7563 Literal* literal = expr->right()->AsLiteral();
7564 if (literal ==
NULL)
return false;
7565 if (!literal->handle()->IsString())
return false;
7566 if (!call->name()->IsEqualTo(
CStrVector(
"_ClassOf")))
return false;
7567 ASSERT(call->arguments()->length() == 1);
7572 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
7573 ASSERT(!HasStackOverflow());
7576 switch (expr->op()) {
7578 return VisitComma(expr);
7581 return VisitLogicalExpression(expr);
7583 return VisitArithmeticExpression(expr);
7588 void HGraphBuilder::VisitComma(BinaryOperation* expr) {
7592 Visit(expr->right());
7596 void HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
7597 bool is_logical_and = expr->op() ==
Token::AND;
7598 if (ast_context()->IsTest()) {
7602 if (is_logical_and) {
7605 context->if_false()));
7614 if (eval_right->HasPredecessor()) {
7615 eval_right->SetJoinId(expr->RightId());
7617 Visit(expr->right());
7620 }
else if (ast_context()->
IsValue()) {
7627 unsigned test_id = expr->left()->test_id();
7628 ToBooleanStub::Types expected(
oracle()->ToBooleanTypes(test_id));
7629 HBranch* test = is_logical_and
7630 ?
new(zone()) HBranch(Top(), eval_right, empty_block, expected)
7631 :
new(zone()) HBranch(Top(), empty_block, eval_right, expected);
7638 HBasicBlock* join_block =
7644 ASSERT(ast_context()->IsEffect());
7650 if (is_logical_and) {
7651 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
7653 CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
7662 if (empty_block->HasPredecessor()) {
7663 empty_block->SetJoinId(expr->id());
7668 if (right_block->HasPredecessor()) {
7669 right_block->SetJoinId(expr->RightId());
7677 HBasicBlock* join_block =
7678 CreateJoin(empty_block, right_block, expr->id());
7686 void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
7689 HValue* right =
Pop();
7690 HValue* left =
Pop();
7691 HInstruction* instr = BuildBinaryOperation(expr, left, right);
7692 instr->set_position(expr->position());
7697 void HGraphBuilder::TraceRepresentation(
Token::Value op,
7700 Representation rep) {
7701 if (!FLAG_trace_representation)
return;
7705 PrintF(
"Operation %s has type info %s, %schange representation assumption "
7706 "for %s (ID %d) from %s to %s\n",
7709 flexible ?
"" :
" DO NOT ",
7712 value->representation().Mnemonic(),
7717 Representation HGraphBuilder::ToRepresentation(TypeInfo info) {
7726 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
7727 HTypeof* typeof_expr,
7728 Handle<String> check) {
7730 HValue* value = typeof_expr->value();
7731 HTypeofIsAndBranch* instr =
new(zone()) HTypeofIsAndBranch(value, check);
7732 instr->set_position(expr->position());
7737 static bool MatchLiteralCompareNil(HValue* left,
7742 if (left->IsConstant() &&
7752 static bool MatchLiteralCompareTypeof(HValue* left,
7755 HTypeof** typeof_expr,
7756 Handle<String>* check) {
7757 if (left->IsTypeof() &&
7759 right->IsConstant() &&
7769 static bool IsLiteralCompareTypeof(HValue* left,
7772 HTypeof** typeof_expr,
7773 Handle<String>* check) {
7774 return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) ||
7775 MatchLiteralCompareTypeof(right, op, left, typeof_expr, check);
7779 static bool IsLiteralCompareNil(HValue* left,
7784 return MatchLiteralCompareNil(left, op, right, nil, expr) ||
7785 MatchLiteralCompareNil(right, op, left, nil, expr);
7789 static bool IsLiteralCompareBool(HValue* left,
7792 return op == Token::EQ_STRICT &&
7793 ((left->IsConstant() &&
HConstant::cast(left)->handle()->IsBoolean()) ||
7794 (right->IsConstant() &&
HConstant::cast(right)->handle()->IsBoolean()));
7798 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
7799 ASSERT(!HasStackOverflow());
7802 if (IsClassOfTest(expr)) {
7803 CallRuntime* call = expr->left()->AsCallRuntime();
7804 ASSERT(call->arguments()->length() == 1);
7805 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
7806 HValue* value =
Pop();
7807 Literal* literal = expr->right()->AsLiteral();
7809 HClassOfTestAndBranch* instr =
7810 new(zone()) HClassOfTestAndBranch(value, rhs);
7811 instr->set_position(expr->position());
7815 TypeInfo type_info =
oracle()->CompareType(expr);
7818 if (type_info.IsUninitialized()) {
7828 HValue* right =
Pop();
7829 HValue* left =
Pop();
7832 HTypeof* typeof_expr =
NULL;
7833 Handle<String>
check;
7834 if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) {
7835 return HandleLiteralCompareTypeof(expr, typeof_expr, check);
7837 HValue* sub_expr =
NULL;
7839 if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) {
7842 if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) {
7843 return HandleLiteralCompareNil(expr, sub_expr,
kNullValue);
7845 if (IsLiteralCompareBool(left, op, right)) {
7846 HCompareObjectEqAndBranch* result =
7847 new(zone()) HCompareObjectEqAndBranch(left, right);
7848 result->set_position(expr->position());
7852 if (op == Token::INSTANCEOF) {
7857 VariableProxy* proxy = expr->right()->AsVariableProxy();
7858 bool global_function = (proxy !=
NULL) && proxy->var()->IsUnallocated();
7859 if (global_function &&
7860 info()->has_global_object() &&
7861 !info()->global_object()->IsAccessCheckNeeded()) {
7862 Handle<String> name = proxy->name();
7863 Handle<GlobalObject> global(info()->global_object());
7864 LookupResult lookup(isolate());
7865 global->Lookup(*name, &lookup);
7866 if (lookup.IsFound() &&
7867 lookup.type() ==
NORMAL &&
7868 lookup.GetValue()->IsJSFunction()) {
7872 if (!isolate()->heap()->InNewSpace(*candidate)) {
7880 if (target.is_null()) {
7881 HInstanceOf* result =
new(zone()) HInstanceOf(context, left, right);
7882 result->set_position(expr->position());
7886 HInstanceOfKnownGlobal* result =
7887 new(zone()) HInstanceOfKnownGlobal(context, left, target);
7888 result->set_position(expr->position());
7892 HIn* result =
new(zone()) HIn(context, left, right);
7893 result->set_position(expr->position());
7895 }
else if (type_info.IsNonPrimitive()) {
7898 case Token::EQ_STRICT: {
7900 Handle<Map> map =
oracle()->GetCompareMap(expr);
7901 if (!map.is_null()) {
7906 HCompareObjectEqAndBranch* result =
7907 new(zone()) HCompareObjectEqAndBranch(left, right);
7908 result->set_position(expr->position());
7915 HCompareObjectEqAndBranch* result =
7916 new(zone()) HCompareObjectEqAndBranch(left, right);
7917 result->set_position(expr->position());
7922 return Bailout(
"Unsupported non-primitive compare");
7924 }
else if (type_info.IsString() &&
oracle()->IsSymbolCompare(expr) &&
7925 (op ==
Token::EQ || op == Token::EQ_STRICT)) {
7930 HCompareObjectEqAndBranch* result =
7931 new(zone()) HCompareObjectEqAndBranch(left, right);
7932 result->set_position(expr->position());
7935 Representation r = ToRepresentation(type_info);
7937 HCompareGeneric* result =
7938 new(zone()) HCompareGeneric(context, left, right, op);
7939 result->set_position(expr->position());
7942 HCompareIDAndBranch* result =
7943 new(zone()) HCompareIDAndBranch(left, right, op);
7944 result->set_position(expr->position());
7945 result->SetInputRepresentation(r);
7952 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
7955 ASSERT(!HasStackOverflow());
7960 HIsNilAndBranch* instr =
new(zone()) HIsNilAndBranch(value, kind, nil);
7961 instr->set_position(expr->position());
7966 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
7967 ASSERT(!HasStackOverflow());
7970 HThisFunction*
self =
new(zone()) HThisFunction(
7977 ASSERT(globals_.is_empty());
7978 AstVisitor::VisitDeclarations(declarations);
7979 if (!globals_.is_empty()) {
7981 isolate()->factory()->NewFixedArray(globals_.length(),
TENURED);
7982 for (
int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.
at(i));
8001 globals_.
Add(variable->
name(), zone());
8003 ? isolate()->factory()->the_hole_value()
8004 : isolate()->factory()->undefined_value(), zone());
8017 HStoreContextSlot* store =
new(zone()) HStoreContextSlot(
8020 if (store->HasObservableSideEffects())
AddSimulate(proxy->
id());
8024 return Bailout(
"unsupported lookup slot in declaration");
8029 void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) {
8030 VariableProxy* proxy = declaration->proxy();
8031 Variable* variable = proxy->var();
8032 switch (variable->location()) {
8034 globals_.
Add(variable->name(), zone());
8035 Handle<SharedFunctionInfo>
function =
8038 if (
function.is_null())
return SetStackOverflow();
8039 globals_.
Add(
function, zone());
8045 HValue* value =
Pop();
8051 HValue* value =
Pop();
8053 HStoreContextSlot* store =
new(zone()) HStoreContextSlot(
8056 if (store->HasObservableSideEffects())
AddSimulate(proxy->id());
8060 return Bailout(
"unsupported lookup slot in declaration");
8065 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* declaration) {
8070 void HGraphBuilder::VisitImportDeclaration(ImportDeclaration* declaration) {
8075 void HGraphBuilder::VisitExportDeclaration(ExportDeclaration* declaration) {
8080 void HGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) {
8085 void HGraphBuilder::VisitModuleVariable(ModuleVariable* module) {
8090 void HGraphBuilder::VisitModulePath(ModulePath* module) {
8095 void HGraphBuilder::VisitModuleUrl(ModuleUrl* module) {
8102 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
8103 ASSERT(call->arguments()->length() == 1);
8104 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8105 HValue* value =
Pop();
8106 HIsSmiAndBranch* result =
new(zone()) HIsSmiAndBranch(value);
8111 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
8112 ASSERT(call->arguments()->length() == 1);
8113 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8114 HValue* value =
Pop();
8115 HHasInstanceTypeAndBranch* result =
8116 new(zone()) HHasInstanceTypeAndBranch(value,
8123 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
8124 ASSERT(call->arguments()->length() == 1);
8125 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8126 HValue* value =
Pop();
8127 HHasInstanceTypeAndBranch* result =
8133 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
8134 ASSERT(call->arguments()->length() == 1);
8135 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8136 HValue* value =
Pop();
8137 HHasCachedArrayIndexAndBranch* result =
8138 new(zone()) HHasCachedArrayIndexAndBranch(value);
8143 void HGraphBuilder::GenerateIsArray(CallRuntime* call) {
8144 ASSERT(call->arguments()->length() == 1);
8145 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8146 HValue* value =
Pop();
8147 HHasInstanceTypeAndBranch* result =
8148 new(zone()) HHasInstanceTypeAndBranch(value,
JS_ARRAY_TYPE);
8153 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
8154 ASSERT(call->arguments()->length() == 1);
8155 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8156 HValue* value =
Pop();
8157 HHasInstanceTypeAndBranch* result =
8163 void HGraphBuilder::GenerateIsObject(CallRuntime* call) {
8164 ASSERT(call->arguments()->length() == 1);
8165 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8166 HValue* value =
Pop();
8167 HIsObjectAndBranch* result =
new(zone()) HIsObjectAndBranch(value);
8172 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
8173 return Bailout(
"inlined runtime function: IsNonNegativeSmi");
8177 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
8178 ASSERT(call->arguments()->length() == 1);
8179 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8180 HValue* value =
Pop();
8181 HIsUndetectableAndBranch* result =
8182 new(zone()) HIsUndetectableAndBranch(value);
8187 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
8188 CallRuntime* call) {
8190 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
8195 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
8196 ASSERT(call->arguments()->length() == 0);
8204 return ast_context()->
ReturnControl(
new(zone()) HIsConstructCallAndBranch,
8211 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
8216 ASSERT(call->arguments()->length() == 0);
8218 new(zone()) HArgumentsElements(
false));
8219 HArgumentsLength* result =
new(zone()) HArgumentsLength(elements);
8224 void HGraphBuilder::GenerateArguments(CallRuntime* call) {
8229 ASSERT(call->arguments()->length() == 1);
8230 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8231 HValue* index =
Pop();
8233 new(zone()) HArgumentsElements(
false));
8234 HInstruction* length =
AddInstruction(
new(zone()) HArgumentsLength(elements));
8235 HAccessArgumentsAt* result =
8236 new(zone()) HAccessArgumentsAt(elements, length, index);
8242 void HGraphBuilder::GenerateClassOf(CallRuntime* call) {
8245 return Bailout(
"inlined runtime function: ClassOf");
8249 void HGraphBuilder::GenerateValueOf(CallRuntime* call) {
8250 ASSERT(call->arguments()->length() == 1);
8251 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8252 HValue* value =
Pop();
8253 HValueOf* result =
new(zone()) HValueOf(value);
8258 void HGraphBuilder::GenerateDateField(CallRuntime* call) {
8259 ASSERT(call->arguments()->length() == 2);
8261 Smi* index =
Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle()));
8262 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8263 HValue* date =
Pop();
8264 HDateField* result =
new(zone()) HDateField(date, index);
8269 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
8270 ASSERT(call->arguments()->length() == 2);
8271 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8272 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
8273 HValue* value =
Pop();
8274 HValue*
object =
Pop();
8276 HIsSmiAndBranch* smicheck =
new(zone()) HIsSmiAndBranch(
object);
8280 smicheck->SetSuccessorAt(0, if_smi);
8281 smicheck->SetSuccessorAt(1, if_heap_object);
8287 HHasInstanceTypeAndBranch* typecheck =
8288 new(zone()) HHasInstanceTypeAndBranch(
object,
JS_VALUE_TYPE);
8291 typecheck->SetSuccessorAt(0, if_js_value);
8292 typecheck->SetSuccessorAt(1, not_js_value);
8294 not_js_value->Goto(join);
8298 Handle<String> name = isolate()->factory()->undefined_symbol();
8304 if_js_value->Goto(join);
8305 join->SetJoinId(call->id());
8312 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
8313 ASSERT(call->arguments()->length() == 2);
8314 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8315 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
8316 HValue* index =
Pop();
8317 HValue*
string =
Pop();
8319 HStringCharCodeAt* result = BuildStringCharCodeAt(context,
string, index);
8325 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
8326 ASSERT(call->arguments()->length() == 1);
8327 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8328 HValue* char_code =
Pop();
8330 HStringCharFromCode* result =
8331 new(zone()) HStringCharFromCode(context, char_code);
8337 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
8338 ASSERT(call->arguments()->length() == 2);
8339 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8340 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
8341 HValue* index =
Pop();
8342 HValue*
string =
Pop();
8344 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context,
string, index);
8346 HStringCharFromCode* result =
8347 new(zone()) HStringCharFromCode(context, char_code);
8353 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
8354 ASSERT(call->arguments()->length() == 2);
8355 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8356 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
8357 HValue* right =
Pop();
8358 HValue* left =
Pop();
8359 HCompareObjectEqAndBranch* result =
8360 new(zone()) HCompareObjectEqAndBranch(left, right);
8365 void HGraphBuilder::GenerateLog(CallRuntime* call) {
8372 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
8374 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
8376 HRandom* result =
new(zone()) HRandom(global_object);
8382 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) {
8383 ASSERT_EQ(2, call->arguments()->length());
8384 CHECK_ALIVE(VisitArgumentList(call->arguments()));
8386 HCallStub* result =
new(zone()) HCallStub(context, CodeStub::StringAdd, 2);
8393 void HGraphBuilder::GenerateSubString(CallRuntime* call) {
8394 ASSERT_EQ(3, call->arguments()->length());
8395 CHECK_ALIVE(VisitArgumentList(call->arguments()));
8404 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) {
8405 ASSERT_EQ(2, call->arguments()->length());
8406 CHECK_ALIVE(VisitArgumentList(call->arguments()));
8409 new(zone()) HCallStub(context, CodeStub::StringCompare, 2);
8416 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
8417 ASSERT_EQ(4, call->arguments()->length());
8418 CHECK_ALIVE(VisitArgumentList(call->arguments()));
8420 HCallStub* result =
new(zone()) HCallStub(context, CodeStub::RegExpExec, 4);
8427 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
8428 ASSERT_EQ(3, call->arguments()->length());
8429 CHECK_ALIVE(VisitArgumentList(call->arguments()));
8432 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3);
8439 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
8440 return Bailout(
"inlined runtime function: GetFromCache");
8445 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) {
8446 ASSERT_EQ(1, call->arguments()->length());
8447 CHECK_ALIVE(VisitArgumentList(call->arguments()));
8450 new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
8457 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
8459 int arg_count = call->arguments()->length() - 1;
8462 for (
int i = 0; i < arg_count; ++i) {
8463 CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
8465 CHECK_ALIVE(VisitForValue(call->arguments()->last()));
8467 HValue*
function =
Pop();
8471 HHasInstanceTypeAndBranch* typecheck =
8476 typecheck->SetSuccessorAt(0, if_jsfunction);
8477 typecheck->SetSuccessorAt(1, if_nonfunction);
8482 new(zone()) HInvokeFunction(context,
function, arg_count));
8484 Push(invoke_result);
8485 if_jsfunction->Goto(join);
8489 new(zone()) HCallFunction(context,
function, arg_count));
8492 if_nonfunction->Goto(join);
8495 join->SetJoinId(call->id());
8501 void HGraphBuilder::GenerateMathPow(CallRuntime* call) {
8502 ASSERT_EQ(2, call->arguments()->length());
8503 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8504 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
8505 HValue* right =
Pop();
8506 HValue* left =
Pop();
8507 HPower* result =
new(zone()) HPower(left, right);
8512 void HGraphBuilder::GenerateMathSin(CallRuntime* call) {
8513 ASSERT_EQ(1, call->arguments()->length());
8514 CHECK_ALIVE(VisitArgumentList(call->arguments()));
8517 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
8524 void HGraphBuilder::GenerateMathCos(CallRuntime* call) {
8525 ASSERT_EQ(1, call->arguments()->length());
8526 CHECK_ALIVE(VisitArgumentList(call->arguments()));
8529 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
8536 void HGraphBuilder::GenerateMathTan(CallRuntime* call) {
8537 ASSERT_EQ(1, call->arguments()->length());
8538 CHECK_ALIVE(VisitArgumentList(call->arguments()));
8541 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
8548 void HGraphBuilder::GenerateMathLog(CallRuntime* call) {
8549 ASSERT_EQ(1, call->arguments()->length());
8550 CHECK_ALIVE(VisitArgumentList(call->arguments()));
8553 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
8560 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
8561 return Bailout(
"inlined runtime function: MathSqrt");
8566 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
8567 return Bailout(
"inlined runtime function: IsRegExpEquivalent");
8571 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
8572 ASSERT(call->arguments()->length() == 1);
8573 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8574 HValue* value =
Pop();
8575 HGetCachedArrayIndex* result =
new(zone()) HGetCachedArrayIndex(value);
8580 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
8581 return Bailout(
"inlined runtime function: FastAsciiArrayJoin");
8585 #undef CHECK_BAILOUT
8593 : closure_(closure),
8595 assigned_variables_(4, zone),
8597 parameter_count_(0),
8611 assigned_variables_(0, zone),
8613 parameter_count_(0),
8619 ast_id_(other->ast_id()),
8630 : closure_(closure),
8631 values_(arguments, zone),
8632 assigned_variables_(0, zone),
8633 frame_type_(frame_type),
8634 parameter_count_(arguments),
8639 ast_id_(AstNode::kNoNumber),
8644 void HEnvironment::Initialize(
int parameter_count,
8651 int total = parameter_count + specials_count_ + local_count + stack_height;
8652 values_.Initialize(total + 4,
zone());
8653 for (
int i = 0; i < total; ++i) values_.Add(
NULL, zone());
8657 void HEnvironment::Initialize(
const HEnvironment* other) {
8658 closure_ = other->closure();
8659 values_.AddAll(other->values_, zone());
8660 assigned_variables_.
AddAll(other->assigned_variables_, zone());
8661 frame_type_ = other->frame_type_;
8662 parameter_count_ = other->parameter_count_;
8663 local_count_ = other->local_count_;
8664 if (other->outer_ !=
NULL) outer_ = other->outer_->
Copy();
8665 pop_count_ = other->pop_count_;
8666 push_count_ = other->push_count_;
8667 ast_id_ = other->ast_id_;
8673 ASSERT(values_.length() == other->values_.length());
8675 int length = values_.length();
8676 for (
int i = 0; i <
length; ++i) {
8677 HValue* value = values_[i];
8678 if (value !=
NULL && value->
IsPhi() && value->
block() == block) {
8685 }
else if (values_[i] != other->values_[i]) {
8689 HValue* old_value = values_[i];
8690 for (
int j = 0; j < block->
predecessors()->length(); j++) {
8694 this->values_[i] = phi;
8703 if (!assigned_variables_.
Contains(index)) {
8704 assigned_variables_.
Add(index,
zone());
8706 values_[index] = value;
8710 bool HEnvironment::HasExpressionAt(
int index)
const {
8711 return index >= parameter_count_ + specials_count_ + local_count_;
8722 int count = index_from_top + 1;
8723 int index = values_.length() - count;
8724 ASSERT(HasExpressionAt(index));
8727 if (push_count_ < count) {
8729 pop_count_ += (count - push_count_);
8730 push_count_ = count;
8732 values_[index] = value;
8737 for (
int i = 0; i < count; ++i) {
8757 for (
int i = 0; i < values_.length(); ++i) {
8760 new_env->values_[i] = phi;
8761 loop_header->
AddPhi(phi);
8771 int arguments)
const {
8774 arguments + 1,
zone());
8775 for (
int i = 0; i <= arguments; ++i) {
8789 bool is_construct)
const {
8795 int arity =
function->scope()->num_parameters();
8798 outer->
Drop(arguments + 1);
8805 outer = CreateStubEnvironment(outer, target,
JS_CONSTRUCT, arguments);
8808 if (arity != arguments) {
8816 for (
int i = 0; i <= arity; ++i) {
8817 HValue* push = (i <= arguments) ?
8824 if ((target->shared()->native() || !
function->is_classic_mode()) &&
8829 for (
int i = arity + 2; i < inner->
length(); ++i) {
8839 for (
int i = 0; i <
length(); i++) {
8840 if (i == 0) stream->
Add(
"parameters\n");
8844 stream->
Add(
"expressions\n");
8846 HValue* val = values_.at(i);
8847 stream->
Add(
"%d: ", i);
8851 stream->
Add(
"NULL");
8868 Tag tag(
this,
"compilation");
8870 PrintStringProperty(
"name", *name->ToCString());
8871 PrintStringProperty(
"method", *name->ToCString());
8886 void HTracer::Trace(
const char* name,
HGraph* graph,
LChunk* chunk) {
8887 Tag tag(
this,
"cfg");
8888 PrintStringProperty(
"name", name);
8890 for (
int i = 0; i < blocks->length(); i++) {
8892 Tag block_tag(
this,
"block");
8893 PrintBlockProperty(
"name", current->
block_id());
8894 PrintIntProperty(
"from_bci", -1);
8895 PrintIntProperty(
"to_bci", -1);
8899 trace_.
Add(
"predecessors");
8900 for (
int j = 0; j < current->
predecessors()->length(); ++j) {
8905 PrintEmptyProperty(
"predecessors");
8909 PrintEmptyProperty(
"successors");
8912 trace_.
Add(
"successors");
8913 for (HSuccessorIterator it(current->
end()); !it.Done(); it.Advance()) {
8914 trace_.
Add(
" \"B%d\"", it.Current()->block_id());
8919 PrintEmptyProperty(
"xhandlers");
8923 PrintStringProperty(
"flags", flags);
8931 if (chunk !=
NULL) {
8943 Tag states_tag(
this,
"states");
8944 Tag locals_tag(
this,
"locals");
8945 int total = current->
phis()->length();
8946 PrintIntProperty(
"size", current->
phis()->length());
8947 PrintStringProperty(
"method",
"None");
8948 for (
int j = 0; j < total; ++j) {
8949 HPhi* phi = current->
phis()->at(j);
8951 trace_.
Add(
"%d ", phi->merged_index());
8952 phi->PrintNameTo(&trace_);
8954 phi->PrintTo(&trace_);
8960 Tag HIR_tag(
this,
"HIR");
8961 HInstruction* instruction = current->
first();
8962 while (instruction !=
NULL) {
8964 int uses = instruction->
UseCount();
8966 trace_.
Add(
"%d %d ", bci, uses);
8967 instruction->PrintNameTo(&trace_);
8969 instruction->PrintTo(&trace_);
8970 trace_.
Add(
" <|@\n");
8971 instruction = instruction->next();
8976 if (chunk !=
NULL) {
8977 Tag LIR_tag(
this,
"LIR");
8980 if (first_index != -1 && last_index != -1) {
8982 for (
int i = first_index; i <= last_index; ++i) {
8983 LInstruction* linstr = instructions->at(i);
8984 if (linstr !=
NULL) {
8988 linstr->PrintTo(&trace_);
8989 trace_.
Add(
" <|@\n");
8999 Tag tag(
this,
"intervals");
9000 PrintStringProperty(
"name", name);
9003 for (
int i = 0; i < fixed_d->
length(); ++i) {
9004 TraceLiveRange(fixed_d->
at(i),
"fixed", allocator->zone());
9008 for (
int i = 0; i < fixed->
length(); ++i) {
9009 TraceLiveRange(fixed->
at(i),
"fixed", allocator->zone());
9013 for (
int i = 0; i < live_ranges->length(); ++i) {
9014 TraceLiveRange(live_ranges->
at(i),
"object", allocator->zone());
9019 void HTracer::TraceLiveRange(
LiveRange* range,
const char* type,
9026 int assigned_reg = op->
index();
9027 if (op->IsDoubleRegister()) {
9028 trace_.
Add(
" \"%s\"",
9031 ASSERT(op->IsRegister());
9036 if (op->IsDoubleStackSlot()) {
9037 trace_.
Add(
" \"double_stack:%d\"", op->index());
9039 ASSERT(op->IsStackSlot());
9040 trace_.
Add(
" \"stack:%d\"", op->index());
9043 int parent_index = -1;
9045 parent_index = range->
parent()->
id();
9047 parent_index = range->
id();
9050 int hint_index = -1;
9051 if (op !=
NULL && op->IsUnallocated()) {
9054 trace_.
Add(
" %d %d", parent_index, hint_index);
9056 while (cur_interval !=
NULL && range->
Covers(cur_interval->start())) {
9057 trace_.
Add(
" [%d, %d[",
9058 cur_interval->start().Value(),
9059 cur_interval->end().Value());
9060 cur_interval = cur_interval->next();
9063 UsePosition* current_pos = range->
first_pos();
9064 while (current_pos !=
NULL) {
9065 if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
9066 trace_.
Add(
" %d M", current_pos->pos().Value());
9068 current_pos = current_pos->next();
9071 trace_.
Add(
" \"\"\n");
9076 void HTracer::FlushToFile() {
9083 source_size_ += info->shared_info()->SourceSize();
9088 PrintF(
"Timing results:\n");
9090 for (
int i = 0; i < timing_.length(); ++i) {
9094 for (
int i = 0; i < names_.length(); ++i) {
9095 PrintF(
"%30s", names_[i]);
9096 double ms =
static_cast<double>(timing_[i]) / 1000;
9097 double percent =
static_cast<double>(timing_[i]) * 100 / sum;
9098 PrintF(
" - %7.3f ms / %4.1f %% ", ms, percent);
9100 unsigned size = sizes_[i];
9101 double size_percent =
static_cast<double>(size) * 100 / total_size_;
9102 PrintF(
" %8u bytes / %4.1f %%\n", size, size_percent);
9104 double source_size_in_kb =
static_cast<double>(source_size_) / 1024;
9105 double normalized_time = source_size_in_kb > 0
9106 ? (
static_cast<double>(sum) / 1000) / source_size_in_kb
9108 double normalized_bytes = source_size_in_kb > 0
9109 ? total_size_ / source_size_in_kb
9111 PrintF(
"%30s - %7.3f ms %7.3f bytes\n",
"Sum",
9112 normalized_time, normalized_bytes);
9113 PrintF(
"---------------------------------------------------------------\n");
9114 PrintF(
"%30s - %7.3f ms (%.1f times slower than full code gen)\n",
9116 static_cast<double>(total_) / 1000,
9117 static_cast<double>(total_) / full_code_gen_);
9122 if (name == HPhase::kFullCodeGen) {
9123 full_code_gen_ += ticks;
9124 }
else if (name == HPhase::kTotal) {
9127 total_size_ += size;
9128 for (
int i = 0; i < names_.length(); ++i) {
9129 if (names_[i] == name) {
9130 timing_[i] += ticks;
9142 const char*
const HPhase::kFullCodeGen =
"Full code generator";
9143 const char*
const HPhase::kTotal =
"Total";
9146 void HPhase::Begin(
const char* name,
9149 LAllocator* allocator) {
9153 allocator_ = allocator;
9154 if (allocator !=
NULL && chunk_ ==
NULL) {
9155 chunk_ = allocator->chunk();
9157 if (FLAG_hydrogen_stats) start_ =
OS::Ticks();
9162 void HPhase::End()
const {
9163 if (FLAG_hydrogen_stats) {
9171 if (FLAG_trace_hydrogen &&
9175 if (allocator_ !=
NULL) {
9181 if (graph_ !=
NULL) graph_->Verify(
false);
9182 if (allocator_ !=
NULL) allocator_->Verify();
void MarkAsDeoptimizing()
static HPhi * cast(HValue *value)
void SetInitialEnvironment(HEnvironment *env)
bool HasObservableSideEffects() const
bool UpdateInferredType()
#define INLINE_FUNCTION_LIST(F)
static LUnallocated * cast(LOperand *op)
FunctionState(HGraphBuilder *owner, CompilationInfo *info, TypeFeedbackOracle *oracle, ReturnHandlingFlag return_handling)
static const int kDefaultMaxOptCount
#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)
bool IsDeoptimizing() const
HBasicBlock * if_true() const
GVNFlagSet gvn_flags() const
VariableDeclaration * function() const
bool IsExternalArrayElementsKind(ElementsKind kind)
bool Contains(const T &elm) const
const char * ToCString(const v8::String::Utf8Value &value)
void set_entry(HEnterInlined *entry)
HValueMap * Copy(Zone *zone) const
void PrintF(const char *format,...)
BoundsCheckBbData(BoundsCheckKey *key, int32_t lower_offset, int32_t upper_offset, HBasicBlock *bb, HBoundsCheck *check, BoundsCheckBbData *next_in_bb, BoundsCheckBbData *father_in_dt)
virtual void ReturnControl(HControlInstruction *instr, int ast_id)
void set_block_id(int id)
virtual HValue * Canonicalize()
virtual void SetDehoisted(bool is_dehoisted)=0
static const int kDeclarationsId
static uint32_t encode(boolvalue)
HInstruction * previous() const
static const char * Name(Value tok)
static Smi * FromInt(int value)
static bool MakeCode(CompilationInfo *info)
void AddLeaveInlined(HValue *return_value, HBasicBlock *target, FunctionState *state=NULL)
static const int kEnumCacheBridgeIndicesCacheIndex
bool CheckUsesForFlag(Flag f)
#define TRACE_GVN_4(msg, a1, a2, a3, a4)
void Delete(BoundsCheckKey *key)
LiveRange * parent() const
HValue * LookupContext() const
virtual int ContinueId() const =0
bool Dominates(HBasicBlock *other) const
value format" "after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, "report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true, "garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true, "flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true, "use incremental marking") DEFINE_bool(incremental_marking_steps, true, "do incremental marking steps") DEFINE_bool(trace_incremental_marking, false, "trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true, "Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false, "Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true, "use inline caching") DEFINE_bool(native_code_counters, false, "generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false, "Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true, "Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false, "Never perform compaction on full GC-testing only") DEFINE_bool(compact_code_space, true, "Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true, "Flush inline caches prior to mark compact collection and" "flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0, "Default seed for initializing random generator" "(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true, "allows verbose printing") DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") DEFINE_bool(trace_sim, false, "Trace simulator execution") DEFINE_bool(check_icache, false, "Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8, "Stack alingment in bytes in simulator(4 or 8, 8 is default)") DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true, "randomize hashes to avoid predictable hash collisions" "(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0, "Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false, "activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true, "generate optimized regexp code") DEFINE_bool(testing_bool_flag, true, "testing_bool_flag") DEFINE_int(testing_int_flag, 13, "testing_int_flag") DEFINE_float(testing_float_flag, 2.5, "float-flag") DEFINE_string(testing_string_flag, "Hello, world!", "string-flag") DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness") DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") DEFINE_bool(help, false, "Print usage message, including flags, on console") DEFINE_bool(dump_counters, false, "Dump counters on exit") DEFINE_string(map_counters, "", "Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT, "Pass all remaining arguments to the script.Alias for\"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#43"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2#define FLAG_MODE_DEFINE_DEFAULTS#1"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flag-definitions.h"1#define FLAG_FULL(ftype, ctype, nam, def, cmt)#define FLAG_READONLY(ftype, ctype, nam, def, cmt)#define DEFINE_implication(whenflag, thenflag)#define DEFINE_bool(nam, def, cmt)#define DEFINE_int(nam, def, cmt)#define DEFINE_float(nam, def, cmt)#define DEFINE_string(nam, def, cmt)#define DEFINE_args(nam, def, cmt)#define FLAG DEFINE_bool(use_strict, false,"enforce strict mode") DEFINE_bool(es5_readonly, false,"activate correct semantics for inheriting readonliness") DEFINE_bool(es52_globals, false,"activate new semantics for global var declarations") DEFINE_bool(harmony_typeof, false,"enable harmony semantics for typeof") DEFINE_bool(harmony_scoping, false,"enable harmony block scoping") DEFINE_bool(harmony_modules, false,"enable harmony modules (implies block scoping)") DEFINE_bool(harmony_proxies, false,"enable harmony proxies") DEFINE_bool(harmony_collections, false,"enable harmony collections (sets, maps, and weak maps)") DEFINE_bool(harmony, false,"enable all harmony features (except typeof)") DEFINE_implication(harmony, harmony_scoping) DEFINE_implication(harmony, harmony_modules) DEFINE_implication(harmony, harmony_proxies) DEFINE_implication(harmony, harmony_collections) DEFINE_implication(harmony_modules, harmony_scoping) DEFINE_bool(packed_arrays, false,"optimizes arrays that have no holes") DEFINE_bool(smi_only_arrays, true,"tracks arrays with only smi values") DEFINE_bool(clever_optimizations, true,"Optimize object size, Array shift, DOM strings and string +") DEFINE_bool(unbox_double_arrays, true,"automatically unbox arrays of doubles") DEFINE_bool(string_slices, true,"use string slices") DEFINE_bool(crankshaft, true,"use crankshaft") DEFINE_string(hydrogen_filter,"","optimization filter") DEFINE_bool(use_range, true,"use hydrogen range analysis") DEFINE_bool(eliminate_dead_phis, true,"eliminate dead phis") DEFINE_bool(use_gvn, true,"use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true,"use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true,"use function inlining") DEFINE_int(max_inlined_source_size, 600,"maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196,"maximum number of AST nodes considered for a single inlining") DEFINE_int(max_inlined_nodes_cumulative, 196,"maximum cumulative number of AST nodes considered for inlining") DEFINE_bool(loop_invariant_code_motion, true,"loop invariant code motion") DEFINE_bool(collect_megamorphic_maps_from_stub_cache, true,"crankshaft harvests type feedback from stub cache") DEFINE_bool(hydrogen_stats, false,"print statistics for hydrogen") DEFINE_bool(trace_hydrogen, false,"trace generated hydrogen to file") DEFINE_string(trace_phase,"Z","trace generated IR for specified phases") DEFINE_bool(trace_inlining, false,"trace inlining decisions") DEFINE_bool(trace_alloc, false,"trace register allocator") DEFINE_bool(trace_all_uses, false,"trace all use positions") DEFINE_bool(trace_range, false,"trace range analysis") DEFINE_bool(trace_gvn, false,"trace global value numbering") DEFINE_bool(trace_representation, false,"trace representation types") DEFINE_bool(stress_pointer_maps, false,"pointer map for every instruction") DEFINE_bool(stress_environments, false,"environment for every instruction") DEFINE_int(deopt_every_n_times, 0,"deoptimize every n times a deopt point is passed") DEFINE_bool(trap_on_deopt, false,"put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true,"deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true,"polymorphic inlining") DEFINE_bool(use_osr, true,"use on-stack replacement") DEFINE_bool(array_bounds_checks_elimination, false,"perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, false,"perform array index dehoisting") DEFINE_bool(trace_osr, false,"trace on-stack replacement") DEFINE_int(stress_runs, 0,"number of stress runs") DEFINE_bool(optimize_closures, true,"optimize closures") DEFINE_bool(inline_construct, true,"inline constructor calls") DEFINE_bool(inline_arguments, true,"inline functions with arguments object") DEFINE_int(loop_weight, 1,"loop weight for representation inference") DEFINE_bool(optimize_for_in, true,"optimize functions containing for-in loops") DEFINE_bool(experimental_profiler, true,"enable all profiler experiments") DEFINE_bool(watch_ic_patching, false,"profiler considers IC stability") DEFINE_int(frame_count, 1,"number of stack frames inspected by the profiler") DEFINE_bool(self_optimization, false,"primitive functions trigger their own optimization") DEFINE_bool(direct_self_opt, false,"call recompile stub directly when self-optimizing") DEFINE_bool(retry_self_opt, false,"re-try self-optimization if it failed") DEFINE_bool(count_based_interrupts, false,"trigger profiler ticks based on counting instead of timing") DEFINE_bool(interrupt_at_exit, false,"insert an interrupt check at function exit") DEFINE_bool(weighted_back_edges, false,"weight back edges by jump distance for interrupt triggering") DEFINE_int(interrupt_budget, 5900,"execution budget before interrupt is triggered") DEFINE_int(type_info_threshold, 15,"percentage of ICs that must have type info to allow optimization") DEFINE_int(self_opt_count, 130,"call count before self-optimization") DEFINE_implication(experimental_profiler, watch_ic_patching) DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, retry_self_opt) DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, interrupt_at_exit) DEFINE_implication(experimental_profiler, weighted_back_edges) DEFINE_bool(trace_opt_verbose, false,"extra verbose compilation tracing") DEFINE_implication(trace_opt_verbose, trace_opt) DEFINE_bool(debug_code, false,"generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false,"emit comments in code disassembly") DEFINE_bool(enable_sse2, true,"enable use of SSE2 instructions if available") DEFINE_bool(enable_sse3, true,"enable use of SSE3 instructions if available") DEFINE_bool(enable_sse4_1, true,"enable use of SSE4.1 instructions if available") DEFINE_bool(enable_cmov, true,"enable use of CMOV instruction if available") DEFINE_bool(enable_rdtsc, true,"enable use of RDTSC instruction if available") DEFINE_bool(enable_sahf, true,"enable use of SAHF instruction if available (X64 only)") DEFINE_bool(enable_vfp3, true,"enable use of VFP3 instructions if available - this implies ""enabling ARMv7 instructions (ARM only)") DEFINE_bool(enable_armv7, true,"enable use of ARMv7 instructions if available (ARM only)") DEFINE_bool(enable_fpu, true,"enable use of MIPS FPU instructions if available (MIPS only)") DEFINE_string(expose_natives_as, NULL,"expose natives in global object") DEFINE_string(expose_debug_as, NULL,"expose debug in global object") DEFINE_bool(expose_gc, false,"expose gc extension") DEFINE_bool(expose_externalize_string, false,"expose externalize string extension") DEFINE_int(stack_trace_limit, 10,"number of stack frames to capture") DEFINE_bool(builtins_in_stack_traces, false,"show built-in functions in stack traces") DEFINE_bool(disable_native_files, false,"disable builtin natives files") DEFINE_bool(inline_new, true,"use fast inline allocation") DEFINE_bool(stack_trace_on_abort, true,"print a stack trace if an assertion failure occurs") DEFINE_bool(trace, false,"trace function calls") DEFINE_bool(mask_constants_with_cookie, true,"use random jit cookie to mask large constants") DEFINE_bool(lazy, true,"use lazy compilation") DEFINE_bool(trace_opt, false,"trace lazy optimization") DEFINE_bool(trace_opt_stats, false,"trace lazy optimization statistics") DEFINE_bool(opt, true,"use adaptive optimizations") DEFINE_bool(always_opt, false,"always try to optimize functions") DEFINE_bool(prepare_always_opt, false,"prepare for turning on always opt") DEFINE_bool(trace_deopt, false,"trace deoptimization") DEFINE_int(min_preparse_length, 1024,"minimum length for automatic enable preparsing") DEFINE_bool(always_full_compiler, false,"try to use the dedicated run-once backend for all code") DEFINE_bool(trace_bailout, false,"print reasons for falling back to using the classic V8 backend") DEFINE_bool(compilation_cache, true,"enable compilation cache") DEFINE_bool(cache_prototype_transitions, true,"cache prototype transitions") DEFINE_bool(trace_debug_json, false,"trace debugging JSON request/response") DEFINE_bool(debugger_auto_break, true,"automatically set the debug break flag when debugger commands are ""in the queue") DEFINE_bool(enable_liveedit, true,"enable liveedit experimental feature") DEFINE_bool(break_on_abort, true,"always cause a debug break before aborting") DEFINE_int(stack_size, kPointerSize *123,"default size of stack region v8 is allowed to use (in kBytes)") DEFINE_int(max_stack_trace_source_length, 300,"maximum length of function source code printed in a stack trace.") DEFINE_bool(always_inline_smi_code, false,"always inline smi code in non-opt code") DEFINE_int(max_new_space_size, 0,"max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0,"max size of the old generation (in Mbytes)") DEFINE_int(max_executable_size, 0,"max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false,"always perform global GCs") DEFINE_int(gc_interval,-1,"garbage collect after <n> allocations") DEFINE_bool(trace_gc, false,"print one trace line following each garbage collection") DEFINE_bool(trace_gc_nvp, false,"print one detailed trace line in name=value format ""after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false,"print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false,"print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false,"report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true,"garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true,"flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true,"use incremental marking") DEFINE_bool(incremental_marking_steps, true,"do incremental marking steps") DEFINE_bool(trace_incremental_marking, false,"trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true,"Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false,"Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true,"use inline caching") DEFINE_bool(native_code_counters, false,"generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false,"Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true,"Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false,"Never perform compaction on full GC - testing only") DEFINE_bool(compact_code_space, true,"Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true,"Flush inline caches prior to mark compact collection and ""flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0,"Default seed for initializing random generator ""(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true,"allows verbose printing") DEFINE_bool(allow_natives_syntax, false,"allow natives syntax") DEFINE_bool(trace_sim, false,"Trace simulator execution") DEFINE_bool(check_icache, false,"Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0,"Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8,"Stack alingment in bytes in simulator (4 or 8, 8 is default)") DEFINE_bool(trace_exception, false,"print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false,"preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true,"randomize hashes to avoid predictable hash collisions ""(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0,"Fixed seed to use to hash property keys (0 means random)""(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false,"activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true,"generate optimized regexp code") DEFINE_bool(testing_bool_flag, true,"testing_bool_flag") DEFINE_int(testing_int_flag, 13,"testing_int_flag") DEFINE_float(testing_float_flag, 2.5,"float-flag") DEFINE_string(testing_string_flag,"Hello, world!","string-flag") DEFINE_int(testing_prng_seed, 42,"Seed used for threading test randomness") DEFINE_string(testing_serialization_file,"/tmp/serdes","file in which to serialize heap") DEFINE_bool(help, false,"Print usage message, including flags, on console") DEFINE_bool(dump_counters, false,"Dump counters on exit") DEFINE_string(map_counters,"","Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT,"Pass all remaining arguments to the script. Alias for \"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#47"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2 namespace{struct Flag{enum FlagType{TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS} name
HBasicBlock * block() const
static Handle< T > cast(Handle< S > that)
static Representation Integer32()
void Insert(BoundsCheckKey *key, BoundsCheckBbData *data, Zone *zone)
static bool Analyze(CompilationInfo *info)
HConstant * GetConstant1()
bool HasIllegalRedeclaration() const
Expression * condition() const
void SetArgumentsObject(HArgumentsObject *object)
static HCheckInstanceType * NewIsString(HValue *value, Zone *zone)
void Finish(HControlInstruction *last)
HInstruction * first() const
static TypeInfo Unknown()
HEnvironment * CopyForInlining(Handle< JSFunction > target, int arguments, FunctionLiteral *function, HConstant *undefined, CallKind call_kind, bool is_construct) const
static const int kNoNumber
#define DECLARE_FLAG(type)
HEnvironment * arguments_environment()
Location location() const
HValue * Lookup(Variable *variable) const
void AssumeRepresentation(Representation r)
void MarkAsLoopSuccessorDominator()
void Bind(Variable *variable, HValue *value)
virtual void ReturnValue(HValue *value)
HGraphBuilder * owner() const
void FinishExitWithDeoptimization(HDeoptimize::UseEnvironment has_uses)
HValue * GetRedundantReplacement()
static LifetimePosition FromInstructionIndex(int index)
HBasicBlock * dominator() const
static const int kMaxLiteralDepth
void SetExpressionStackAt(int index_from_top, HValue *value)
virtual int OperandCount()
FrameType frame_type() const
bool CheckArgumentsPhiUses()
HRangeAnalysis(HGraph *graph)
static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags)
static GvnBasicBlockState * CreateEntry(Zone *zone, HBasicBlock *entry_block, HValueMap *entry_map)
int PredecessorIndexOf(HBasicBlock *predecessor) const
static HCheckMaps * NewWithTransitions(HValue *object, Handle< Map > map, Zone *zone)
List< Handle< Map > > MapHandleList
#define ASSERT(condition)
BoundsCheckBbData * NextInBasicBlock() const
void SaveTiming(const char *name, int64_t ticks, unsigned size)
void InsertRepresentationChanges()
HBasicBlock * current_block() const
HConstant * GetConstantTrue()
virtual void ReturnInstruction(HInstruction *instr, int ast_id)
static HInstruction * NewHMod(Zone *zone, HValue *context, HValue *left, HValue *right)
void AddSimulate(int ast_id)
const ZoneList< HBasicBlock * > * predecessors() const
HBoundsCheck * Check() const
HEnvironment * Copy() const
static bool IsCompileTimeValue(Expression *expression)
static HInstruction * NewHMul(Zone *zone, HValue *context, HValue *left, HValue *right)
static SharedFunctionInfo * cast(Object *obj)
HControlInstruction * end() const
void DetachLoopInformation()
bool HasPredecessor() const
static Representation Double()
HEnvironment * CopyAsLoopHeader(HBasicBlock *block) const
virtual void ReturnValue(HValue *value)
FunctionState * function_state() const
int GetMaximumValueID() const
bool Equals(const Representation &other)
bool ContainsAnyOf(const EnumSet &set) const
int parameter_count() const
bool IsFastElementsKind(ElementsKind kind)
Representation representation() const
ZoneList< HUnknownOSRValue * > * osr_values()
virtual void ReturnInstruction(HInstruction *instr, int ast_id)
static const int kFunctionEntryId
Handle< String > name() const
virtual void ReturnControl(HControlInstruction *instr, int ast_id)
static HStatistics * Instance()
TypeFeedbackOracle * oracle() const
static const int kMaxSize
void AssignCommonDominator(HBasicBlock *other)
static Smi * cast(Object *object)
HEnvironment * environment() const
HEnvironment * last_environment() const
static const char * AllocationIndexToString(int index)
void DehoistSimpleArrayIndexComputations()
static Handle< ScopeInfo > Create(Scope *scope, Zone *zone)
const ZoneList< HValue * > * values() const
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 instructions(ARM only)") DEFINE_bool(enable_armv7
static bool Parse(CompilationInfo *info, int flags)
int last_instruction_index() const
void TraceLithium(const char *name, LChunk *chunk)
Handle< String > SubString(Handle< String > str, int start, int end, PretenureFlag pretenure)
static HCheckInstanceType * NewIsJSArray(HValue *value, Zone *zone)
AstContext(HGraphBuilder *owner, Expression::Context kind)
static void PrintCode(Handle< Code > code, CompilationInfo *info)
void Add(Vector< const char > format, Vector< FmtElm > elms)
HConstant * GetConstantFalse()
bool Covers(LifetimePosition position)
LOperand * CreateAssignedOperand(Zone *zone)
static HCheckInstanceType * NewIsSpecObject(HValue *value, Zone *zone)
void Initialize(CompilationInfo *info)
BoundsCheckKey * Key() const
void RemovePhi(HPhi *phi)
int virtual_register() const
void VisitDeclarations(ZoneList< Declaration * > *declarations)
bool ExpressionStackIsEmpty() const
VariableProxy * proxy() const
bool Equals(HValue *other)
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
static const int kMaxVirtualRegisters
void set_osr_loop_entry(HBasicBlock *entry)
BoundsCheckBbData ** LookupOrInsert(BoundsCheckKey *key, Zone *zone)
void set_arguments_elements(HArgumentsElements *arguments_elements)
int32_t LowerOffset() const
void RemoveZeroOperations()
const ZoneList< HBasicBlock * > * dominated_blocks() const
EnumSet< GVNFlag > GVNFlagSet
int first_expression_index() const
bool IsFastPackedElementsKind(ElementsKind kind)
HConstant * GetConstantUndefined() const
BoundsCheckTable(Zone *zone)
int num_stack_slots() const
void AddIncomingEdge(HBasicBlock *block, HEnvironment *other)
HBasicBlock(HGraph *graph)
static HUnaryOperation * cast(HValue *value)
bool HasRegisterAssigned() const
#define TRACE_GVN_1(msg, a1)
static bool IsValidElementsTransition(ElementsKind from_kind, ElementsKind to_kind)
static bool IsValid(intptr_t value)
virtual void ReturnControl(HControlInstruction *instr, int ast_id)=0
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
void PostProcessLoopHeader(IterationStatement *stmt)
bool HasEnvironment() const
void MarkAsInlineReturnTarget()
void set_current_block(HBasicBlock *block)
T * NewArray(size_t size)
int32_t UpperOffset() const
void UpdateEnvironment(HEnvironment *env)
BreakAndContinueScope * break_scope() const
static Value NegateCompareOp(Value op)
#define GVN_TRACKED_FLAG_LIST(V)
HArgumentsElements * arguments_elements()
ZoneList< HValue * > * arguments_values()
void EliminateUnreachablePhis()
void set_undefined_constant(HConstant *constant)
static HTracer * Instance()
virtual HValue * OperandAt(int index)
static HInstruction * NewHSub(Zone *zone, HValue *context, HValue *left, HValue *right)
GvnBasicBlockState * next_in_dominator_tree_traversal(Zone *zone, HBasicBlock **dominator)
void AddInput(HValue *value)
UseInterval * first_interval() const
Entry * Lookup(void *key, uint32_t hash, bool insert, ZoneAllocationPolicyallocator=ZoneAllocationPolicy())
static unsigned allocation_size_
HValue * ExpressionStackAt(int index_from_top) const
HEnvironment(HEnvironment *outer, Scope *scope, Handle< JSFunction > closure, Zone *zone)
static void VPrint(const char *format, va_list args)
SparseSet(Zone *zone, int capacity)
static TestContext * cast(AstContext *context)
HGraphBuilder(CompilationInfo *info, TypeFeedbackOracle *oracle, Zone *zone)
void PropagateDeoptimizingMark()
HInstruction * next() const
HGlobalValueNumberer(HGraph *graph, CompilationInfo *info)
static double TimeCurrentMillis()
int32_t Integer32Value() const
HBasicBlock * osr_loop_entry()
static GVNFlag DependsOnFlagFromInt(int x)
int num_parameters() const
HConstant * GetConstantMinus1()
static int SizeFor(int length)
static HInstruction * NewHShr(Zone *zone, HValue *context, HValue *left, HValue *right)
static HInstruction * NewHBitwise(Zone *zone, Token::Value op, HValue *context, HValue *left, HValue *right)
static Value InvertCompareOp(Value op)
bool Contains(int n) const
HInstruction * last() const
static bool IsEqualityOp(Value op)
SmartArrayPointer< char > GetGVNFlagsString(GVNFlagSet flags)
void MarkDeoptimizeOnUndefined()
void ComputeMinusZeroChecks()
static ScopeInfo * Empty()
HStackCheckEliminator(HGraph *graph)
LOperand * FirstHint() const
BoundsCheckBbData * FatherInDominatorTree() const
void RecordDeletedPhi(int merge_index)
virtual HValue * GetKey()=0
void DeleteAndReplaceWith(HValue *other)
Vector< const char > CStrVector(const char *data)
static HInstruction * NewHDiv(Zone *zone, HValue *context, HValue *left, HValue *right)
#define GVN_UNTRACKED_FLAG_LIST(V)
void AddEnvironmentValue(HValue *value, Zone *zone)
virtual intptr_t Hashcode()
HBasicBlock * CreateBasicBlock()
bool IsInlineReturnTarget() const
static int SizeFor(int length)
bool OffsetIsCovered(int32_t offset) const
void BindContext(HValue *value)
void PrintNameTo(StringStream *stream)
static BoundsCheckKey * Create(Zone *zone, HBoundsCheck *check, int32_t *offset)
const int kElementsKindCount
void InsertAfter(HInstruction *previous)
static const int kHeaderSize
int specials_count() const
virtual int SuccessorCount()=0
void SetValueAt(int index, HValue *value)
static int SNPrintF(Vector< char > str, const char *format,...)
HArgumentsObject * GetArgumentsObject() const
const ZoneList< HBasicBlock * > * blocks() const
virtual void SetSuccessorAt(int i, HBasicBlock *block)=0
int first_instruction_index() const
HBasicBlock * BasicBlock() const
#define CHECK_ALIVE(call)
UsePosition * first_pos() const
Handle< Code > Compile(CompilationInfo *info, Zone *zone)
int LoopNestingDepth() const
const ZoneList< HPhi * > * phi_list() const
HBasicBlock * parent_loop_header() const
bool IsLoopSuccessorDominator() const
void InitializeInferredTypes()
HEnvironment * DiscardInlined(bool drop_extra)
void SetOperandAt(int index, HValue *value)
void FinishExit(HControlInstruction *instruction)
ElementsKind GetInitialFastElementsKind()
bool CheckFlag(Flag f) const
FunctionSorter(int index, int ticks, int ast_length, int src_length)
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, PropertyType type=NORMAL, int argc=-1, InlineCacheHolderFlag holder=OWN_MAP)
int AppendChars(const char *filename, const char *str, int size, bool verbose)
static Handle< Object > CreateArrayLiteralBoilerplate(Isolate *isolate, Handle< FixedArray > literals, Handle< FixedArray > elements)
HValue * IndexBase() const
void InsertBefore(HInstruction *next)
HBasicBlock * CreateJoin(HBasicBlock *first, HBasicBlock *second, int join_id)
void Goto(HBasicBlock *block, FunctionState *state=NULL)
void EliminateRedundantPhis()
bool binding_needs_init() const
HLoopInformation * loop_information() const
bool IsStartBlock() const
static Handle< T > null()
void CoverCheck(HBoundsCheck *new_check, int32_t new_offset)
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kThisPropertyAssignmentsOffset flag
void * Remove(void *key, uint32_t hash)
virtual void SetIndexOffset(uint32_t index_offset)=0
static HInstruction * NewHAdd(Zone *zone, HValue *context, HValue *left, HValue *right)
bool IsLoopHeader() const
#define ASSERT_EQ(v1, v2)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
virtual void ReturnValue(HValue *value)
void SetBlock(HBasicBlock *block)
void PrintTo(StringStream *stream)
static Handle< SharedFunctionInfo > BuildFunctionInfo(FunctionLiteral *node, Handle< Script > script)
void set_parent_loop_header(HBasicBlock *block)
#define TRACE_GVN_2(msg, a1, a2)
ContainedInLattice AddRange(ContainedInLattice containment, const int *ranges, int ranges_length, Interval new_range)
#define ASSERT_NE(v1, v2)
static const uint32_t kDefaultHashMapCapacity
HConstant * GetConstantHole()
CompilationInfo * compilation_info()
static const int kEnumCacheBridgeCacheIndex
const T & at(int index) const
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
HGraph(CompilationInfo *info, Zone *zone)
HBasicBlock * if_false() const
static const char * AllocationIndexToString(int index)
static bool HasCustomCallGenerator(Handle< JSFunction > function)
void EliminateRedundantBoundsChecks()
static GVNFlag ChangesFlagFromInt(int x)
static const int kMaxInliningLevels
void TraceHydrogen(const char *name, HGraph *graph)
void Bailout(const char *reason)
void AddIndirectUsesTo(int *use_count)
const ZoneList< HPhi * > * phis() const
void TraceCompilation(FunctionLiteral *function)
void AssignLoopSuccessorDominators()
bool HasInteger32Value() const
static Representation None()
static const int kValueOffset
bool is_function_scope() const
virtual void ReturnInstruction(HInstruction *instr, int ast_id)=0
virtual void ReturnControl(HControlInstruction *instr, int ast_id)
static Representation Tagged()
Handle< JSFunction > closure() const
SmartArrayPointer< const char > ToCString() const
static HCheckInstanceType * NewIsSymbol(HValue *value, Zone *zone)
#define INLINE_RUNTIME_FUNCTION_LIST(F)
void SetJoinId(int ast_id)
virtual void SetKey(HValue *key)=0
VariableMode mode() const
static Handle< Code > MakeCodeEpilogue(MacroAssembler *masm, Code::Flags flags, CompilationInfo *info)
void AttachLoopInformation()
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag, CompilationInfo *info, Handle< SharedFunctionInfo > shared)
static HInstruction * NewHSar(Zone *zone, HValue *context, HValue *left, HValue *right)
static HInstruction * NewHShl(Zone *zone, HValue *context, HValue *left, HValue *right)
static HValue * cast(HValue *value)
void check(i::Vector< const char > string)
HSideEffectMap * dominators()
#define CHECK_BAILOUT(call)
static void MakeCodePrologue(CompilationInfo *info)
virtual void ReturnValue(HValue *value)=0
virtual void ReturnInstruction(HInstruction *instr, int ast_id)
void TraceLiveRanges(const char *name, LAllocator *allocator)
void set_osr_values(ZoneList< HUnknownOSRValue * > *values)
LOperand * GetSpillOperand() const
HBasicBlock * entry_block() const
static JSObject * cast(Object *obj)
static const int kMaxLiteralProperties
HInferRepresentation(HGraph *graph)
void AddInstruction(HInstruction *instr)
ZoneList< Declaration * > * declarations()
static char * StrChr(char *str, int c)
void AddAll(const List< T, AllocationPolicy > &other, AllocationPolicy allocator=AllocationPolicy())
void TraceGVN(const char *msg,...)
HInstruction * AddInstruction(HInstruction *instr)
HBasicBlock * function_return()
bool IsFastDoubleElementsKind(ElementsKind kind)
const ZoneList< LInstruction * > * instructions() const
HUseIterator uses() const
#define TRACE_GVN_5(msg, a1, a2, a3, a4, a5)
friend class FunctionState
HEnvironment * CopyWithoutHistory() const
void AddSimulate(int ast_id)
static JSFunction * cast(Object *obj)