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(BailoutId 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);
169 bool drop_extra = state !=
NULL &&
207 int length = predecessors_.length();
209 for (
int i = 0; i < length; i++) {
216 ->VerifyBailoutId(ast_id));
217 simulate->set_ast_id(ast_id);
224 while (current !=
NULL) {
225 if (current ==
this)
return true;
261 void HBasicBlock::RegisterPredecessor(
HBasicBlock* pred) {
270 for (
int i = 0; i < phis_.length(); ++i) {
271 phis_[i]->AddInput(incoming_env->
values()->at(i));
281 predecessors_.Add(pred,
zone());
285 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
286 ASSERT(!dominated_blocks_.Contains(block));
290 while (index < dominated_blocks_.length() &&
291 dominated_blocks_[index]->block_id() < block->block_id()) {
294 dominated_blocks_.InsertAt(index, block,
zone());
299 if (dominator_ ==
NULL) {
301 other->AddDominatedBlock(
this);
306 while (first != second) {
315 if (dominator_ != first) {
316 ASSERT(dominator_->dominated_blocks_.Contains(
this));
317 dominator_->dominated_blocks_.RemoveElement(
this);
319 first->AddDominatedBlock(
this);
336 int outstanding_successors = 1;
341 for (HPredecessorIterator it(dominator_candidate); !it.Done();
346 outstanding_successors--;
358 ASSERT(outstanding_successors >= 0);
360 if (outstanding_successors == 0 &&
361 (parent_loop_header ==
this && !dominator_candidate->
IsLoopHeader())) {
365 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
374 outstanding_successors++;
382 for (
int i = 0; i < predecessors_.length(); ++i) {
383 if (predecessors_[i] == predecessor)
return i;
391 void HBasicBlock::Verify() {
397 if (predecessors_.length() > 1) {
398 for (
int i = 0; i < predecessors_.length(); ++i) {
407 this->back_edges_.Add(block, block->
zone());
415 for (
int i = 0; i < back_edges_.length(); ++i) {
426 void HLoopInformation::AddBlock(
HBasicBlock* block) {
433 blocks_.Add(block, block->
zone());
434 for (
int i = 0; i < block->
predecessors()->length(); ++i) {
450 ReachabilityAnalyzer(HBasicBlock* entry_block,
452 HBasicBlock* dont_visit)
454 stack_(16, entry_block->zone()),
455 reachable_(block_count, entry_block->zone()),
456 dont_visit_(dont_visit) {
457 PushBlock(entry_block);
461 int visited_count()
const {
return visited_count_; }
462 const BitVector* reachable()
const {
return &reachable_; }
465 void PushBlock(HBasicBlock* block) {
466 if (block !=
NULL && block != dont_visit_ &&
467 !reachable_.Contains(block->block_id())) {
468 reachable_.Add(block->block_id());
469 stack_.Add(block, block->zone());
475 while (!stack_.is_empty()) {
476 HControlInstruction* end = stack_.RemoveLast()->end();
477 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
478 PushBlock(it.Current());
484 ZoneList<HBasicBlock*> stack_;
485 BitVector reachable_;
486 HBasicBlock* dont_visit_;
490 void HGraph::Verify(
bool do_full_verify)
const {
491 for (
int i = 0; i < blocks_.length(); i++) {
492 HBasicBlock* block = blocks_.at(i);
498 HInstruction* current = block->first();
499 ASSERT(current !=
NULL && current->IsBlockEntry());
500 while (current !=
NULL) {
501 ASSERT((current->next() ==
NULL) == current->IsControlInstruction());
502 ASSERT(current->block() == block);
504 current = current->next();
508 HBasicBlock* first = block->end()->FirstSuccessor();
509 HBasicBlock* second = block->end()->SecondSuccessor();
514 ASSERT(first->predecessors()->Contains(block));
515 if (second !=
NULL) {
516 ASSERT(second->predecessors()->Contains(block));
521 for (
int j = 0; j < block->phis()->length(); j++) {
522 HPhi* phi = block->phis()->at(j);
528 if (block->predecessors()->length() >= 2) {
530 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,
571 Handle<Object> value) {
572 if (!pointer->is_set()) {
573 HConstant* constant =
new(
zone()) HConstant(value,
576 pointer->set(constant);
578 return pointer->get();
582 HConstant* HGraph::GetConstantInt32(SetOncePointer<HConstant>* pointer,
584 if (!pointer->is_set()) {
585 HConstant* constant =
588 pointer->set(constant);
590 return pointer->get();
595 return GetConstantInt32(&constant_1_, 1);
600 return GetConstantInt32(&constant_minus1_, -1);
605 return GetConstant(&constant_true_,
isolate()->factory()->true_value());
610 return GetConstant(&constant_false_,
isolate()->factory()->false_value());
615 return GetConstant(&constant_hole_,
isolate()->factory()->the_hole_value());
621 : function_state_(
NULL),
626 current_block_(
NULL),
628 globals_(10, info->zone()),
630 inline_bailout_(
false) {
634 function_state_= &initial_function_state_;
642 }
else if (second ==
NULL) {
646 first->
Goto(join_block);
647 second->
Goto(join_block);
657 if (continue_block !=
NULL) {
658 if (exit_block !=
NULL) exit_block->
Goto(continue_block);
660 return continue_block;
666 HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
667 HBasicBlock* loop_entry,
668 HBasicBlock* body_exit,
669 HBasicBlock* loop_successor,
670 HBasicBlock* break_block) {
671 if (body_exit !=
NULL) body_exit->
Goto(loop_entry);
672 loop_entry->PostProcessLoopHeader(statement);
673 if (break_block !=
NULL) {
674 if (loop_successor !=
NULL) loop_successor->Goto(break_block);
675 break_block->SetJoinId(statement->ExitId());
678 return loop_successor;
689 : isolate_(info->isolate()),
692 blocks_(8, info->zone()),
693 values_(16, info->zone()),
695 uint32_instructions_(
NULL),
698 is_recursive_(
false),
699 use_optimistic_licm_(
false),
700 type_change_checksum_(0) {
711 blocks_.Add(result,
zone());
717 if (!FLAG_use_canonicalizing)
return;
718 HPhase phase(
"H_Canonicalize",
this);
719 for (
int i = 0; i <
blocks()->length(); ++i) {
721 while (instr !=
NULL) {
724 instr = instr->
next();
788 return result->SetupSuccessors(zone, block,
NULL, visited);
795 PerformNonBacktrackingStep(zone, visited, order);
799 return Backtrack(zone, visited, order);
805 : father_(father), child_(
NULL), successor_iterator(
NULL) { }
811 SUCCESSORS_OF_LOOP_HEADER,
813 SUCCESSORS_OF_LOOP_MEMBER
817 PostorderProcessor* SetupSuccessors(Zone* zone,
820 BitVector* visited) {
821 if (block ==
NULL || visited->Contains(block->block_id()) ||
831 visited->Add(block->block_id());
833 if (block->IsLoopHeader()) {
834 kind_ = SUCCESSORS_OF_LOOP_HEADER;
835 loop_header_ =
block;
836 InitializeSuccessors();
837 PostorderProcessor* result = Push(zone);
838 return result->SetupLoopMembers(zone, block, block->loop_information(),
841 ASSERT(block->IsFinished());
844 InitializeSuccessors();
850 PostorderProcessor* SetupLoopMembers(Zone* zone,
852 HLoopInformation*
loop,
853 HBasicBlock* loop_header) {
854 kind_ = LOOP_MEMBERS;
858 InitializeLoopMembers();
862 PostorderProcessor* SetupSuccessorsOfLoopMember(
864 HLoopInformation*
loop,
865 HBasicBlock* loop_header) {
866 kind_ = SUCCESSORS_OF_LOOP_MEMBER;
870 InitializeSuccessors();
875 PostorderProcessor* Push(Zone* zone) {
876 if (child_ ==
NULL) {
877 child_ =
new(zone) PostorderProcessor(
this);
882 void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) {
889 order->Add(block_, zone);
893 PostorderProcessor* Pop(Zone* zone,
895 ZoneList<HBasicBlock*>* order) {
898 case SUCCESSORS_OF_LOOP_HEADER:
899 ClosePostorder(order, zone);
903 case SUCCESSORS_OF_LOOP_MEMBER:
907 return SetupLoopMembers(zone,
block(),
908 block()->loop_information(), loop_header_);
920 PostorderProcessor* Backtrack(Zone* zone,
922 ZoneList<HBasicBlock*>* order) {
923 PostorderProcessor*
parent = Pop(zone, visited, order);
924 while (parent !=
NULL) {
925 PostorderProcessor* next =
926 parent->PerformNonBacktrackingStep(zone, visited, order);
930 parent = parent->Pop(zone, visited, order);
936 PostorderProcessor* PerformNonBacktrackingStep(
939 ZoneList<HBasicBlock*>* order) {
940 HBasicBlock* next_block;
943 next_block = AdvanceSuccessors();
944 if (next_block !=
NULL) {
945 PostorderProcessor* result = Push(zone);
946 return result->SetupSuccessors(zone, next_block,
947 loop_header_, visited);
950 case SUCCESSORS_OF_LOOP_HEADER:
951 next_block = AdvanceSuccessors();
952 if (next_block !=
NULL) {
953 PostorderProcessor* result = Push(zone);
954 return result->SetupSuccessors(zone, next_block,
959 next_block = AdvanceLoopMembers();
960 if (next_block !=
NULL) {
961 PostorderProcessor* result = Push(zone);
962 return result->SetupSuccessorsOfLoopMember(next_block,
963 loop_, loop_header_);
966 case SUCCESSORS_OF_LOOP_MEMBER:
967 next_block = AdvanceSuccessors();
968 if (next_block !=
NULL) {
969 PostorderProcessor* result = Push(zone);
970 return result->SetupSuccessors(zone, next_block,
971 loop_header_, visited);
981 void InitializeSuccessors() {
984 successor_iterator = HSuccessorIterator(block_->
end());
987 HBasicBlock* AdvanceSuccessors() {
988 if (!successor_iterator.Done()) {
989 HBasicBlock* result = successor_iterator.Current();
990 successor_iterator.Advance();
997 void InitializeLoopMembers() {
999 loop_length = loop_->
blocks()->length();
1002 HBasicBlock* AdvanceLoopMembers() {
1003 if (loop_index < loop_length) {
1004 HBasicBlock* result = loop_->
blocks()->at(loop_index);
1013 PostorderProcessor* father_;
1014 PostorderProcessor* child_;
1015 HLoopInformation* loop_;
1016 HBasicBlock* block_;
1017 HBasicBlock* loop_header_;
1020 HSuccessorIterator successor_iterator;
1025 HPhase phase(
"H_Block ordering");
1032 while (postorder !=
NULL) {
1033 postorder = postorder->
PerformStep(
zone(), &visited, &reverse_result);
1037 for (
int i = reverse_result.length() - 1; i >= 0; --i) {
1039 blocks_.Add(b,
zone());
1046 HPhase phase(
"H_Assign dominators",
this);
1047 for (
int i = 0; i < blocks_.length(); ++i) {
1055 for (
int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
1056 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
1065 HPhase phase(
"H_Propagate deoptimizing mark",
this);
1069 void HGraph::MarkAsDeoptimizingRecursively(
HBasicBlock* block) {
1073 MarkAsDeoptimizingRecursively(dominated);
1078 HPhase phase(
"H_Redundant phi elimination",
this);
1084 for (
int i = 0; i < blocks_.length(); ++i) {
1085 worklist.
AddAll(*blocks_[i]->phis(),
zone());
1088 while (!worklist.is_empty()) {
1089 HPhi* phi = worklist.RemoveLast();
1093 if (block ==
NULL)
continue;
1098 if (replacement !=
NULL) {
1100 for (HUseIterator it(phi->
uses()); !it.Done(); it.Advance()) {
1101 HValue* value = it.value();
1112 HPhase phase(
"H_Unreachable phi elimination",
this);
1117 for (
int i = 0; i < blocks_.length(); ++i) {
1118 for (
int j = 0; j < blocks_[i]->phis()->length(); j++) {
1119 HPhi* phi = blocks_[i]->phis()->at(j);
1126 worklist.Add(phi,
zone());
1132 while (!worklist.is_empty()) {
1133 HPhi* phi = worklist.RemoveLast();
1144 for (
int i = 0; i <
phi_list.length(); i++) {
1156 int block_count = blocks_.length();
1157 for (
int i = 0; i < block_count; ++i) {
1158 for (
int j = 0; j < blocks_[i]->phis()->length(); ++j) {
1159 HPhi* phi = blocks_[i]->phis()->at(j);
1169 int block_count = blocks_.length();
1170 for (
int i = 0; i < block_count; ++i) {
1171 for (
int j = 0; j < blocks_[i]->phis()->length(); ++j) {
1172 HPhi* phi = blocks_[i]->phis()->at(j);
1184 int block_count = blocks_.length();
1186 for (
int i = 0; i < block_count; ++i) {
1187 for (
int j = 0; j < blocks_[i]->phis()->length(); ++j) {
1188 HPhi* phi = blocks_[i]->phis()->at(j);
1189 phi_list_->Add(phi,
zone());
1197 for (
int i = 0; i < worklist->length(); ++i) {
1198 ASSERT(!in_worklist.Contains(worklist->
at(i)->id()));
1199 in_worklist.Add(worklist->
at(i)->id());
1202 while (!worklist->is_empty()) {
1203 HValue* current = worklist->RemoveLast();
1204 in_worklist.
Remove(current->id());
1205 if (current->UpdateInferredType()) {
1206 for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) {
1207 HValue* use = it.value();
1208 if (!in_worklist.Contains(use->id())) {
1209 in_worklist.Add(use->id());
1221 graph_(graph), zone_(graph->zone()), changed_ranges_(16, zone_) { }
1226 void TraceRange(
const char* msg, ...);
1230 void InferRange(
HValue* value);
1231 void RollBackTo(
int index);
1240 void HRangeAnalysis::TraceRange(
const char* msg, ...) {
1241 if (FLAG_trace_range) {
1243 va_start(arguments, msg);
1250 void HRangeAnalysis::Analyze() {
1251 HPhase phase(
"H_Range analysis", graph_);
1252 Analyze(graph_->entry_block());
1256 void HRangeAnalysis::Analyze(HBasicBlock* block) {
1257 TraceRange(
"Analyzing block B%d\n", block->block_id());
1259 int last_changed_range = changed_ranges_.length() - 1;
1262 if (block->predecessors()->length() == 1) {
1264 if (pred->end()->IsCompareIDAndBranch()) {
1270 for (
int i = 0; i < block->phis()->length(); ++i) {
1271 HPhi* phi = block->phis()->at(i);
1276 HInstruction* instr = block->first();
1277 while (instr != block->end()) {
1279 instr = instr->next();
1283 for (
int i = 0; i < block->dominated_blocks()->length(); ++i) {
1284 Analyze(block->dominated_blocks()->at(i));
1287 RollBackTo(last_changed_range);
1291 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test,
1292 HBasicBlock* dest) {
1293 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
1294 if (test->GetInputRepresentation().IsInteger32()) {
1296 if (test->SecondSuccessor() == dest) {
1300 UpdateControlFlowRange(op, test->left(), test->right());
1301 UpdateControlFlowRange(inverted_op, test->right(), test->left());
1308 void HRangeAnalysis::UpdateControlFlowRange(
Token::Value op,
1312 Range* range = other->range() !=
NULL ? other->range() : &temp_range;
1313 Range* new_range =
NULL;
1315 TraceRange(
"Control flow range infer %d %s %d\n",
1320 if (op ==
Token::EQ || op == Token::EQ_STRICT) {
1322 new_range = range->Copy(zone_);
1323 }
else if (op == Token::LT || op == Token::LTE) {
1324 new_range = range->CopyClearLower(zone_);
1325 if (op == Token::LT) {
1326 new_range->AddConstant(-1);
1328 }
else if (op == Token::GT || op == Token::GTE) {
1329 new_range = range->CopyClearUpper(zone_);
1330 if (op == Token::GT) {
1331 new_range->AddConstant(1);
1335 if (new_range !=
NULL && !new_range->IsMostGeneric()) {
1341 void HRangeAnalysis::InferRange(HValue* value) {
1342 ASSERT(!value->HasRange());
1343 if (!value->representation().IsNone()) {
1344 value->ComputeInitialRange(zone_);
1345 Range* range = value->range();
1346 TraceRange(
"Initial inferred range of %d (%s) set to [%d,%d]\n",
1355 void HRangeAnalysis::RollBackTo(
int index) {
1356 for (
int i = index + 1; i < changed_ranges_.length(); ++i) {
1357 changed_ranges_[i]->RemoveLastAddedRange();
1359 changed_ranges_.Rewind(index + 1);
1364 Range* original_range = value->range();
1365 value->AddNewRange(range, zone_);
1366 changed_ranges_.Add(value, zone_);
1367 Range* new_range = value->range();
1368 TraceRange(
"Updated range of %d set to [%d,%d]\n",
1371 new_range->upper());
1372 if (original_range !=
NULL) {
1373 TraceRange(
"Original range was [%d,%d]\n",
1374 original_range->lower(),
1375 original_range->upper());
1377 TraceRange(
"New information was [%d,%d]\n",
1385 va_start(arguments, msg);
1392 #define TRACE_GVN_1(msg, a1) \
1393 if (FLAG_trace_gvn) { \
1394 TraceGVN(msg, a1); \
1397 #define TRACE_GVN_2(msg, a1, a2) \
1398 if (FLAG_trace_gvn) { \
1399 TraceGVN(msg, a1, a2); \
1402 #define TRACE_GVN_3(msg, a1, a2, a3) \
1403 if (FLAG_trace_gvn) { \
1404 TraceGVN(msg, a1, a2, a3); \
1407 #define TRACE_GVN_4(msg, a1, a2, a3, a4) \
1408 if (FLAG_trace_gvn) { \
1409 TraceGVN(msg, a1, a2, a3, a4); \
1412 #define TRACE_GVN_5(msg, a1, a2, a3, a4, a5) \
1413 if (FLAG_trace_gvn) { \
1414 TraceGVN(msg, a1, a2, a3, a4, a5); \
1419 : array_size_(other->array_size_),
1420 lists_size_(other->lists_size_),
1421 count_(other->count_),
1422 present_flags_(other->present_flags_),
1423 array_(zone->
NewArray<HValueMapListElement>(other->array_size_)),
1424 lists_(zone->
NewArray<HValueMapListElement>(other->lists_size_)),
1425 free_list_head_(other->free_list_head_) {
1426 memcpy(array_, other->array_, array_size_ *
sizeof(HValueMapListElement));
1427 memcpy(lists_, other->lists_, lists_size_ *
sizeof(HValueMapListElement));
1432 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(flags);
1433 if (!present_flags_.ContainsAnyOf(depends_flags))
return;
1434 present_flags_.RemoveAll();
1435 for (
int i = 0; i < array_size_; ++i) {
1436 HValue* value = array_[i].value;
1437 if (value !=
NULL) {
1441 for (
int current = array_[i].next; current != kNil; current = next) {
1442 next = lists_[current].next;
1443 HValue* value = lists_[current].value;
1447 lists_[current].next = free_list_head_;
1448 free_list_head_ = current;
1451 lists_[current].next = kept;
1456 array_[i].next = kept;
1459 value = array_[i].value;
1462 int head = array_[i].next;
1464 array_[i].value =
NULL;
1466 array_[i].value = lists_[head].value;
1467 array_[i].next = lists_[head].next;
1468 lists_[head].next = free_list_head_;
1469 free_list_head_ = head;
1480 uint32_t hash =
static_cast<uint32_t
>(value->
Hashcode());
1481 uint32_t pos = Bound(hash);
1482 if (array_[pos].value !=
NULL) {
1483 if (array_[pos].value->
Equals(value))
return array_[pos].value;
1484 int next = array_[pos].next;
1485 while (next != kNil) {
1486 if (lists_[next].value->
Equals(value))
return lists_[next].value;
1487 next = lists_[next].next;
1494 void HValueMap::Resize(
int new_size,
Zone* zone) {
1495 ASSERT(new_size > count_);
1500 if (free_list_head_ == kNil) {
1501 ResizeLists(lists_size_ << 1, zone);
1504 HValueMapListElement* new_array =
1505 zone->
NewArray<HValueMapListElement>(new_size);
1506 memset(new_array, 0,
sizeof(HValueMapListElement) * new_size);
1508 HValueMapListElement* old_array = array_;
1509 int old_size = array_size_;
1511 int old_count = count_;
1514 array_size_ = new_size;
1517 if (old_array !=
NULL) {
1519 for (
int i = 0; i < old_size; ++i) {
1520 if (old_array[i].value !=
NULL) {
1521 int current = old_array[i].next;
1522 while (current != kNil) {
1523 Insert(lists_[current].value, zone);
1524 int next = lists_[current].next;
1525 lists_[current].next = free_list_head_;
1526 free_list_head_ = current;
1530 Insert(old_array[i].value, zone);
1535 ASSERT(count_ == old_count);
1539 void HValueMap::ResizeLists(
int new_size, Zone* zone) {
1540 ASSERT(new_size > lists_size_);
1542 HValueMapListElement* new_lists =
1543 zone->NewArray<HValueMapListElement>(new_size);
1544 memset(new_lists, 0,
sizeof(HValueMapListElement) * new_size);
1546 HValueMapListElement* old_lists = lists_;
1547 int old_size = lists_size_;
1549 lists_size_ = new_size;
1552 if (old_lists !=
NULL) {
1553 memcpy(lists_, old_lists, old_size *
sizeof(HValueMapListElement));
1555 for (
int i = old_size; i < lists_size_; ++i) {
1556 lists_[i].next = free_list_head_;
1557 free_list_head_ = i;
1562 void HValueMap::Insert(HValue* value, Zone* zone) {
1565 if (count_ >= array_size_ >> 1) Resize(array_size_ << 1, zone);
1566 ASSERT(count_ < array_size_);
1568 uint32_t pos = Bound(static_cast<uint32_t>(value->Hashcode()));
1569 if (array_[pos].value ==
NULL) {
1570 array_[pos].value = value;
1571 array_[pos].next = kNil;
1573 if (free_list_head_ == kNil) {
1574 ResizeLists(lists_size_ << 1, zone);
1576 int new_element_pos = free_list_head_;
1577 ASSERT(new_element_pos != kNil);
1578 free_list_head_ = lists_[free_list_head_].next;
1579 lists_[new_element_pos].value = value;
1580 lists_[new_element_pos].next = array_[pos].next;
1581 ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value !=
NULL);
1582 array_[pos].next = new_element_pos;
1587 HSideEffectMap::HSideEffectMap() : count_(0) {
1592 HSideEffectMap::HSideEffectMap(HSideEffectMap* other) : count_(other->count_) {
1597 HSideEffectMap& HSideEffectMap::operator= (
const HSideEffectMap& other) {
1598 if (
this != &other) {
1607 if (flags.Contains(changes_flag)) {
1608 if (data_[i] !=
NULL) count_--;
1615 void HSideEffectMap::Store(
GVNFlagSet flags, HInstruction* instr) {
1618 if (flags.Contains(changes_flag)) {
1619 if (data_[i] ==
NULL) count_++;
1637 void HStackCheckEliminator::Process() {
1642 for (
int i = 0; i < graph_->blocks()->length(); i++) {
1643 HBasicBlock* block = graph_->
blocks()->at(i);
1644 if (block->IsLoopHeader()) {
1645 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
1646 HBasicBlock* dominator = back_edge;
1648 HInstruction* instr = dominator->first();
1649 while (instr !=
NULL) {
1650 if (instr->IsCall()) {
1651 block->loop_information()->stack_check()->Eliminate();
1654 instr = instr->next();
1658 if (dominator == block)
break;
1661 dominator = dominator->dominator();
1672 : capacity_(capacity),
1674 dense_(zone->
NewArray<int>(capacity)),
1675 sparse_(zone->
NewArray<int>(capacity)) {
1678 memset(sparse_, 0,
sizeof(sparse_[0]) * capacity);
1683 ASSERT(0 <= n && n < capacity_);
1685 return 0 <= d && d < length_ && dense_[d] == n;
1690 dense_[length_] = n;
1691 sparse_[n] = length_;
1713 removed_side_effects_(
false),
1714 block_side_effects_(graph->blocks()->length(), graph->zone()),
1715 loop_side_effects_(graph->blocks()->length(), graph->zone()),
1716 visited_on_paths_(graph->zone(), graph->blocks()->length()) {
1721 block_side_effects_.AddBlock(
GVNFlagSet(), graph_->blocks()->length(),
1723 loop_side_effects_.AddBlock(
GVNFlagSet(), graph_->blocks()->length(),
1731 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
1734 void AnalyzeGraph();
1735 void ComputeBlockSideEffects();
1736 void LoopInvariantCodeMotion();
1742 bool AllowCodeMotion();
1745 HGraph* graph() {
return graph_; }
1746 CompilationInfo* info() {
return info_; }
1747 Zone* zone()
const {
return graph_->
zone(); }
1750 CompilationInfo* info_;
1751 bool removed_side_effects_;
1754 ZoneList<GVNFlagSet> block_side_effects_;
1757 ZoneList<GVNFlagSet> loop_side_effects_;
1761 SparseSet visited_on_paths_;
1765 bool HGlobalValueNumberer::Analyze() {
1766 removed_side_effects_ =
false;
1767 ComputeBlockSideEffects();
1768 if (FLAG_loop_invariant_code_motion) {
1769 LoopInvariantCodeMotion();
1772 return removed_side_effects_;
1776 void HGlobalValueNumberer::ComputeBlockSideEffects() {
1780 for (
int i = 0; i < loop_side_effects_.length(); ++i) {
1781 loop_side_effects_[i].RemoveAll();
1783 for (
int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1785 HBasicBlock* block = graph_->blocks()->at(i);
1786 HInstruction* instr = block->first();
1787 int id = block->block_id();
1789 while (instr !=
NULL) {
1790 side_effects.
Add(instr->ChangesFlags());
1791 if (instr->IsSoftDeoptimize()) {
1792 block_side_effects_[id].RemoveAll();
1793 side_effects.RemoveAll();
1796 instr = instr->next();
1798 block_side_effects_[id].Add(side_effects);
1801 if (block->IsLoopHeader()) {
1802 loop_side_effects_[id].Add(side_effects);
1806 if (block->HasParentLoopHeader()) {
1807 int header_id = block->parent_loop_header()->block_id();
1808 loop_side_effects_[header_id].Add(block->IsLoopHeader()
1809 ? loop_side_effects_[id]
1817 char underlying_buffer[
kLastFlag * 128];
1818 Vector<char> buffer(underlying_buffer,
sizeof(underlying_buffer));
1821 const char* separator =
"";
1822 const char* comma =
", ";
1824 uint32_t set_depends_on = 0;
1825 uint32_t set_changes = 0;
1826 for (
int bit = 0; bit <
kLastFlag; ++bit) {
1827 if ((flags.
ToIntegral() & (1 << bit)) != 0) {
1835 bool positive_changes = set_changes < (kLastFlag / 2);
1836 bool positive_depends_on = set_depends_on < (kLastFlag / 2);
1837 if (set_changes > 0) {
1838 if (positive_changes) {
1841 offset +=
OS::SNPrintF(buffer + offset,
"changes all except [");
1843 for (
int bit = 0; bit <
kLastFlag; ++bit) {
1844 if (((flags.
ToIntegral() & (1 << bit)) != 0) == positive_changes) {
1845 switch (static_cast<GVNFlag>(bit)) {
1846 #define DECLARE_FLAG(type) \
1847 case kChanges##type: \
1848 offset += OS::SNPrintF(buffer + offset, separator); \
1849 offset += OS::SNPrintF(buffer + offset, #type); \
1850 separator = comma; \
1862 if (set_depends_on > 0) {
1864 if (set_changes > 0) {
1867 if (positive_depends_on) {
1868 offset +=
OS::SNPrintF(buffer + offset,
"depends on [");
1870 offset +=
OS::SNPrintF(buffer + offset,
"depends on all except [");
1872 for (
int bit = 0; bit <
kLastFlag; ++bit) {
1873 if (((flags.
ToIntegral() & (1 << bit)) != 0) == positive_depends_on) {
1874 switch (static_cast<GVNFlag>(bit)) {
1875 #define DECLARE_FLAG(type) \
1876 case kDependsOn##type: \
1877 offset += OS::SNPrintF(buffer + offset, separator); \
1878 offset += OS::SNPrintF(buffer + offset, #type); \
1879 separator = comma; \
1894 size_t string_len = strlen(underlying_buffer) + 1;
1895 ASSERT(string_len <=
sizeof(underlying_buffer));
1896 char* result =
new char[strlen(underlying_buffer) + 1];
1897 memcpy(result, underlying_buffer, string_len);
1902 void HGlobalValueNumberer::LoopInvariantCodeMotion() {
1903 TRACE_GVN_1(
"Using optimistic loop invariant code motion: %s\n",
1904 graph_->use_optimistic_licm() ?
"yes" :
"no");
1905 for (
int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1906 HBasicBlock* block = graph_->blocks()->at(i);
1907 if (block->IsLoopHeader()) {
1908 GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
1909 TRACE_GVN_2(
"Try loop invariant motion for block B%d %s\n",
1915 HBasicBlock* last = block->loop_information()->GetLastBackEdge();
1916 for (
int j = block->block_id(); j <= last->block_id(); ++j) {
1917 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects,
1918 &accumulated_first_time_depends,
1919 &accumulated_first_time_changes);
1926 void HGlobalValueNumberer::ProcessLoopBlock(
1928 HBasicBlock* loop_header,
1932 HBasicBlock* pre_header = loop_header->predecessors()->at(0);
1937 HInstruction* instr = block->first();
1938 while (instr !=
NULL) {
1939 HInstruction* next = instr->next();
1940 bool hoisted =
false;
1942 TRACE_GVN_4(
"Checking instruction %d (%s) %s. Loop %s\n",
1947 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags);
1948 if (can_hoist && !graph()->use_optimistic_licm()) {
1949 can_hoist = block->IsLoopSuccessorDominator();
1953 bool inputs_loop_invariant =
true;
1954 for (
int i = 0; i < instr->OperandCount(); ++i) {
1955 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
1956 inputs_loop_invariant =
false;
1960 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) {
1961 TRACE_GVN_1(
"Hoisting loop invariant instruction %d\n", instr->id());
1964 instr->InsertBefore(pre_header->end());
1965 if (instr->HasSideEffects()) removed_side_effects_ =
true;
1973 GVNFlagSet previous_depends = *first_time_depends;
1974 GVNFlagSet previous_changes = *first_time_changes;
1975 first_time_depends->
Add(instr->DependsOnFlags());
1976 first_time_changes->Add(instr->ChangesFlags());
1977 if (!(previous_depends == *first_time_depends)) {
1978 TRACE_GVN_1(
"Updated first-time accumulated %s\n",
1981 if (!(previous_changes == *first_time_changes)) {
1982 TRACE_GVN_1(
"Updated first-time accumulated %s\n",
1991 bool HGlobalValueNumberer::AllowCodeMotion() {
1992 return info()->shared_info()->opt_count() + 1 < FLAG_max_opt_count;
1996 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1997 HBasicBlock* loop_header) {
2000 return AllowCodeMotion() && !instr->block()->IsDeoptimizing();
2004 GVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
2005 HBasicBlock* dominator, HBasicBlock* dominated) {
2007 for (
int i = 0; i < dominated->predecessors()->length(); ++i) {
2008 HBasicBlock* block = dominated->predecessors()->at(i);
2009 if (dominator->block_id() < block->block_id() &&
2010 block->block_id() < dominated->block_id() &&
2011 visited_on_paths_.Add(block->block_id())) {
2012 side_effects.
Add(block_side_effects_[block->block_id()]);
2013 if (block->IsLoopHeader()) {
2014 side_effects.Add(loop_side_effects_[block->block_id()]);
2016 side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock(
2020 return side_effects;
2048 *dominator =
block();
2050 if (result ==
NULL) {
2052 if (dominator_state !=
NULL) {
2055 *dominator = dominator_state->
block();
2056 result = dominator_state->next_dominated(zone);
2072 map_ = copy_map ? map->
Copy(zone) :
map;
2073 dominated_index_ = -1;
2075 if (dominators !=
NULL) {
2079 bool is_done() {
return dominated_index_ >= length_; }
2081 GvnBasicBlockState(GvnBasicBlockState* previous,
2084 HSideEffectMap* dominators,
2086 : previous_(previous), next_(
NULL) {
2087 Initialize(block, map, dominators,
true, zone);
2090 GvnBasicBlockState* next_dominated(Zone* zone) {
2092 if (dominated_index_ == length_ - 1) {
2100 }
else if (dominated_index_ < length_) {
2109 GvnBasicBlockState* push(Zone* zone,
2111 HSideEffectMap* dominators) {
2112 if (next_ ==
NULL) {
2114 new(zone) GvnBasicBlockState(
this, block,
map(),
dominators, zone);
2116 next_->Initialize(block,
map(), dominators,
true, zone);
2120 GvnBasicBlockState* pop() {
2121 GvnBasicBlockState* result = previous_;
2122 while (result !=
NULL && result->is_done()) {
2123 TRACE_GVN_2(
"Backtracking from block B%d to block b%d\n",
2124 block()->block_id(),
2126 result = result->previous_;
2131 GvnBasicBlockState* previous_;
2132 GvnBasicBlockState* next_;
2133 HBasicBlock* block_;
2135 HSideEffectMap dominators_;
2136 int dominated_index_;
2144 void HGlobalValueNumberer::AnalyzeGraph() {
2145 HBasicBlock* entry_block = graph_->entry_block();
2146 HValueMap* entry_map =
new(zone()) HValueMap(zone());
2147 GvnBasicBlockState* current =
2150 while (current !=
NULL) {
2151 HBasicBlock* block = current->block();
2152 HValueMap* map = current->map();
2153 HSideEffectMap* dominators = current->dominators();
2157 block->IsLoopHeader() ?
" (loop header)" :
"");
2160 if (block->IsLoopHeader()) {
2161 map->Kill(loop_side_effects_[block->block_id()]);
2165 HInstruction* instr = block->first();
2166 while (instr !=
NULL) {
2167 HInstruction* next = instr->next();
2169 if (!flags.IsEmpty()) {
2173 dominators->Store(flags, instr);
2178 ASSERT(!instr->HasObservableSideEffects());
2179 HValue* other = map->Lookup(instr);
2180 if (other !=
NULL) {
2181 ASSERT(instr->Equals(other) && other->Equals(instr));
2182 TRACE_GVN_4(
"Replacing value %d (%s) with value %d (%s)\n",
2187 if (instr->HasSideEffects()) removed_side_effects_ =
true;
2188 instr->DeleteAndReplaceWith(other);
2190 map->Add(instr, zone());
2195 HValue* other = dominators->at(i);
2198 if (instr->DependsOnFlags().Contains(depends_on_flag) &&
2200 TRACE_GVN_5(
"Side-effect #%d in %d (%s) is dominated by %d (%s)\n",
2206 instr->SetSideEffectDominator(changes_flag, other);
2213 HBasicBlock* dominator_block;
2214 GvnBasicBlockState* next =
2215 current->next_in_dominator_tree_traversal(zone(), &dominator_block);
2218 HBasicBlock* dominated = next->block();
2219 HValueMap* successor_map = next->map();
2220 HSideEffectMap* successor_dominators = next->dominators();
2227 if ((!successor_map->IsEmpty() || !successor_dominators->IsEmpty()) &&
2228 dominator_block->block_id() + 1 < dominated->block_id()) {
2229 visited_on_paths_.Clear();
2231 CollectSideEffectsOnPathsToDominatedBlock(dominator_block,
2233 successor_map->Kill(side_effects_on_all_paths);
2234 successor_dominators->Kill(side_effects_on_all_paths);
2246 worklist_(8, graph->zone()),
2247 in_worklist_(graph->GetMaximumValueID(), graph->zone()) { }
2253 void AddToWorklist(
HValue* current);
2254 void InferBasedOnInputs(
HValue* current);
2255 void AddDependantsToWorklist(
HValue* current);
2256 void InferBasedOnUses(
HValue* current);
2258 Zone* zone()
const {
return graph_->zone(); }
2261 ZoneList<HValue*> worklist_;
2262 BitVector in_worklist_;
2266 void HInferRepresentation::AddToWorklist(HValue* current) {
2267 if (current->representation().IsSpecialization())
return;
2269 if (in_worklist_.Contains(current->id()))
return;
2270 worklist_.Add(current, zone());
2271 in_worklist_.Add(current->id());
2279 void HInferRepresentation::InferBasedOnInputs(HValue* current) {
2280 Representation r = current->representation();
2281 if (r.IsSpecialization())
return;
2283 Representation inferred = current->InferredRepresentation();
2284 if (inferred.IsSpecialization()) {
2285 if (FLAG_trace_representation) {
2286 PrintF(
"Changing #%d representation %s -> %s based on inputs\n",
2289 inferred.Mnemonic());
2291 current->ChangeRepresentation(inferred);
2292 AddDependantsToWorklist(current);
2297 void HInferRepresentation::AddDependantsToWorklist(HValue* value) {
2298 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
2299 AddToWorklist(it.value());
2301 for (
int i = 0; i < value->OperandCount(); ++i) {
2302 AddToWorklist(value->OperandAt(i));
2311 void HInferRepresentation::InferBasedOnUses(HValue* value) {
2312 Representation r = value->representation();
2313 if (r.IsSpecialization() || value->HasNoUses())
return;
2315 Representation new_rep = TryChange(value);
2316 if (!new_rep.IsNone()) {
2317 if (!value->representation().Equals(new_rep)) {
2318 if (FLAG_trace_representation) {
2319 PrintF(
"Changing #%d representation %s -> %s based on uses\n",
2322 new_rep.Mnemonic());
2324 value->ChangeRepresentation(new_rep);
2325 AddDependantsToWorklist(value);
2331 Representation HInferRepresentation::TryChange(HValue* value) {
2335 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
2336 HValue* use = it.value();
2337 Representation rep = use->ObservedInputRepresentation(it.index());
2338 if (rep.IsNone())
continue;
2339 if (FLAG_trace_representation) {
2340 PrintF(
"%d %s is used by %d %s as %s\n",
2348 use_count[rep.kind()] += use->LoopWeight();
2353 int non_tagged_count = double_count + int32_count;
2356 if (value->IsPhi() && !value->block()->IsLoopHeader() && tagged_count > 0) {
2364 if (int32_count > 0 && value->IsConvertibleToInteger()) {
2374 void HInferRepresentation::Analyze() {
2375 HPhase phase(
"H_Infer representations", graph_);
2379 const ZoneList<HPhi*>* phi_list = graph_->phi_list();
2380 int phi_count = phi_list->length();
2381 ZoneList<BitVector*> connected_phis(phi_count, graph_->zone());
2382 for (
int i = 0; i < phi_count; ++i) {
2383 phi_list->at(i)->InitRealUses(i);
2384 BitVector* connected_set =
new(zone()) BitVector(phi_count, graph_->zone());
2385 connected_set->Add(i);
2386 connected_phis.Add(connected_set, zone());
2397 for (
int i = phi_count - 1; i >= 0; --i) {
2398 HPhi* phi = phi_list->at(i);
2399 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
2400 HValue* use = it.value();
2403 if (connected_phis[i]->UnionIsChanged(*connected_phis[
id]))
2414 for (
int i = 0; i < phi_count; ++i) {
2415 HPhi* phi = phi_list->at(i);
2416 bool cti = phi->AllOperandsConvertibleToInteger();
2419 for (BitVector::Iterator it(connected_phis.at(i));
2422 HPhi* phi = phi_list->at(it.Current());
2423 phi->set_is_convertible_to_integer(
false);
2424 phi->ResetInteger32Uses();
2430 for (
int i = 0; i < phi_count; ++i) {
2431 HPhi* phi = phi_list->at(i);
2432 for (BitVector::Iterator it(connected_phis.at(i));
2435 int index = it.Current();
2436 HPhi* it_use = phi_list->at(index);
2437 if (index != i) phi->AddNonPhiUsesFrom(it_use);
2442 for (
int i = 0; i < graph_->blocks()->length(); ++i) {
2443 HBasicBlock* block = graph_->blocks()->at(i);
2444 const ZoneList<HPhi*>* phis = block->phis();
2445 for (
int j = 0; j < phis->length(); ++j) {
2446 AddToWorklist(phis->at(j));
2449 HInstruction* current = block->first();
2450 while (current !=
NULL) {
2451 AddToWorklist(current);
2452 current = current->next();
2457 while (!worklist_.is_empty()) {
2458 HValue* current = worklist_.RemoveLast();
2459 in_worklist_.Remove(current->id());
2460 InferBasedOnInputs(current);
2461 InferBasedOnUses(current);
2467 HPhase phase(
"H_Inferring types",
this);
2473 for (
int i = from_inclusive; i <= to_inclusive; ++i) {
2477 for (
int j = 0; j < phis->length(); j++) {
2478 phis->
at(j)->UpdateInferredType();
2481 HInstruction* current = block->
first();
2482 while (current !=
NULL) {
2484 current = current->next();
2488 HBasicBlock* last_back_edge =
2492 i = last_back_edge->block_id();
2495 ZoneList<HValue*> worklist(block->
phis()->length(),
zone());
2496 for (
int j = 0; j < block->
phis()->length(); ++j) {
2499 InferTypes(&worklist);
2505 void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
2506 HValue* current = value;
2507 while (current !=
NULL) {
2508 if (visited->Contains(current->id()))
return;
2511 if (current->IsPhi()) {
2512 visited->Add(current->id());
2514 for (
int i = 0; i < phi->OperandCount(); ++i) {
2515 PropagateMinusZeroChecks(phi->OperandAt(i), visited);
2522 if (current->IsMul()) {
2524 mul->EnsureAndPropagateNotMinusZero(visited);
2525 PropagateMinusZeroChecks(mul->left(), visited);
2526 PropagateMinusZeroChecks(mul->right(), visited);
2527 }
else if (current->IsDiv()) {
2529 div->EnsureAndPropagateNotMinusZero(visited);
2530 PropagateMinusZeroChecks(div->left(), visited);
2531 PropagateMinusZeroChecks(div->right(), visited);
2532 }
else if (current->IsMathMinMax()) {
2534 visited->Add(minmax->id());
2535 PropagateMinusZeroChecks(minmax->left(), visited);
2536 PropagateMinusZeroChecks(minmax->right(), visited);
2539 current = current->EnsureAndPropagateNotMinusZero(visited);
2544 void HGraph::InsertRepresentationChangeForUse(HValue* value,
2547 Representation to) {
2550 HInstruction* next =
NULL;
2551 if (use_value->IsPhi()) {
2552 next = use_value->block()->predecessors()->at(use_index)->end();
2561 HInstruction* new_value =
NULL;
2563 bool deoptimize_on_undefined =
2565 if (value->IsConstant()) {
2568 new_value = is_truncating
2569 ? constant->CopyToTruncatedInt32(
zone())
2570 : constant->CopyToRepresentation(to,
zone());
2573 if (new_value ==
NULL) {
2574 new_value =
new(
zone()) HChange(value, to,
2575 is_truncating, deoptimize_on_undefined);
2578 new_value->InsertBefore(next);
2579 use_value->SetOperandAt(use_index, new_value);
2583 void HGraph::InsertRepresentationChangesForValue(HValue* value) {
2584 Representation r = value->representation();
2585 if (r.IsNone())
return;
2586 if (value->HasNoUses())
return;
2588 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
2589 HValue* use_value = it.value();
2590 int use_index = it.index();
2591 Representation req = use_value->RequiredInputRepresentation(use_index);
2592 if (req.IsNone() || req.Equals(r))
continue;
2593 InsertRepresentationChangeForUse(value, use_value, use_index, req);
2595 if (value->HasNoUses()) {
2596 ASSERT(value->IsConstant());
2597 value->DeleteAndReplaceWith(
NULL);
2602 if (value->IsForceRepresentation()) {
2609 HPhase phase(
"H_Representation changes",
this);
2616 for (
int i = 0; i <
phi_list()->length(); i++) {
2625 for (
int i = 0; i <
phi_list()->length(); i++) {
2635 for (
int i = 0; i < blocks_.length(); ++i) {
2638 for (
int j = 0; j < phis->length(); j++) {
2639 InsertRepresentationChangesForValue(phis->
at(j));
2644 while (current !=
NULL) {
2645 InsertRepresentationChangesForValue(current);
2646 current = current->
next();
2652 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(
HPhi* phi) {
2657 if (input->
IsPhi()) {
2658 RecursivelyMarkPhiDeoptimizeOnUndefined(
HPhi::cast(input));
2665 HPhase phase(
"H_MarkDeoptimizeOnUndefined",
this);
2672 for (
int i = 0; i <
phi_list()->length(); i++) {
2675 for (HUseIterator it(phi->
uses()); !it.Done(); it.Advance()) {
2677 RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
2694 void UnmarkUnsafePhis();
2698 bool Uint32UsesAreSafe(
HValue* uint32val);
2699 bool CheckPhiOperands(
HPhi* phi);
2707 bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) {
2709 if (use->IsBitwise() ||
2715 }
else if (use->IsChange() || use->IsSimulate()) {
2718 }
else if (use->IsStoreKeyedSpecializedArrayElement()) {
2720 HStoreKeyedSpecializedArrayElement* store =
2723 if (store->value() == val) {
2743 bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) {
2744 bool collect_phi_uses =
false;
2745 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
2746 HValue* use = it.value();
2752 collect_phi_uses =
true;
2759 if (!IsSafeUint32Use(uint32val, use)) {
2764 if (collect_phi_uses) {
2765 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
2766 HValue* use = it.value();
2783 void Uint32Analysis::Analyze(HInstruction* current) {
2789 bool Uint32Analysis::CheckPhiOperands(HPhi* phi) {
2795 for (
int j = 0; j < phi->OperandCount(); j++) {
2796 HValue* operand = phi->OperandAt(j);
2799 if (operand->IsConstant() &&
2817 void Uint32Analysis::UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist) {
2819 for (
int j = 0; j < phi->OperandCount(); j++) {
2820 HValue* operand = phi->OperandAt(j);
2823 if (operand->IsPhi()) {
2831 void Uint32Analysis::UnmarkUnsafePhis() {
2833 if (phis_.length() == 0)
return;
2837 ZoneList<HPhi*> worklist(phis_.length(), zone_);
2849 for (
int i = 0; i < phis_.length(); i++) {
2850 HPhi* phi = phis_[i];
2852 if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) {
2853 phis_[phi_count++] = phi;
2855 UnmarkPhi(phi, &worklist);
2863 while (!worklist.is_empty()) {
2864 while (!worklist.is_empty()) {
2865 HPhi* phi = worklist.RemoveLast();
2866 UnmarkPhi(phi, &worklist);
2872 int new_phi_count = 0;
2873 for (
int i = 0; i < phi_count; i++) {
2874 HPhi* phi = phis_[i];
2876 if (CheckPhiOperands(phi)) {
2877 phis_[new_phi_count++] = phi;
2879 UnmarkPhi(phi, &worklist);
2882 phi_count = new_phi_count;
2888 if (!FLAG_opt_safe_uint32_operations || uint32_instructions_ ==
NULL) {
2892 Uint32Analysis analysis(
zone());
2893 for (
int i = 0; i < uint32_instructions_->length(); ++i) {
2896 analysis.Analyze(current);
2904 analysis.UnmarkUnsafePhis();
2910 for (
int i = 0; i < blocks_.length(); ++i) {
2913 current = current->next()) {
2914 if (current->IsChange()) {
2923 PropagateMinusZeroChecks(change->
value(), &visited);
2939 compilation_info_(info),
2941 call_context_(
NULL),
2942 inlining_kind_(inlining_kind),
2943 function_return_(
NULL),
2944 test_context_(
NULL),
2946 arguments_elements_(
NULL),
2947 outer_(owner->function_state()) {
2948 if (outer_ !=
NULL) {
2950 if (owner->ast_context()->
IsTest()) {
2961 new TestContext(owner, cond, outer_oracle, if_true, if_false);
2967 call_context_ = owner->ast_context();
2971 owner->set_function_state(
this);
2976 delete test_context_;
2977 owner_->set_function_state(outer_);
2986 outer_(owner->ast_context()),
2987 for_typeof_(
false) {
2988 owner->set_ast_context(
this);
2997 owner_->set_ast_context(outer_);
3004 (
owner()->environment()->length() == original_length_ &&
3012 (
owner()->environment()->length() == original_length_ + 1 &&
3026 owner()->
Bailout(
"bad value context for arguments value");
3038 ASSERT(!instr->IsControlInstruction());
3058 ASSERT(!instr->IsControlInstruction());
3060 return owner()->
Bailout(
"bad value context for arguments object value");
3071 return owner()->
Bailout(
"bad value context for arguments object value");
3089 ASSERT(!instr->IsControlInstruction());
3091 builder->AddInstruction(instr);
3095 builder->Push(instr);
3096 builder->AddSimulate(ast_id);
3110 empty_true->Goto(
if_true(),
owner()->function_state());
3116 void TestContext::BuildBranch(
HValue* value) {
3123 builder->
Bailout(
"arguments object value in a test context");
3128 ToBooleanStub::Types expected(
oracle()->ToBooleanTypes(test_id));
3129 HBranch* test =
new(
zone()) HBranch(value, empty_true, empty_false, expected);
3132 empty_true->Goto(
if_true(),
owner()->function_state());
3139 #define CHECK_BAILOUT(call) \
3142 if (HasStackOverflow()) return; \
3146 #define CHECK_ALIVE(call) \
3149 if (HasStackOverflow() || current_block() == NULL) return; \
3159 void HGraphBuilder::VisitForEffect(
Expression* expr) {
3166 ValueContext for_value(
this, flag);
3171 void HGraphBuilder::VisitForTypeOf(Expression* expr) {
3173 for_value.set_for_typeof(
true);
3179 void HGraphBuilder::VisitForControl(Expression* expr,
3180 HBasicBlock* true_block,
3181 HBasicBlock* false_block) {
3182 TestContext for_test(
this, expr,
oracle(), true_block, false_block);
3187 void HGraphBuilder::VisitArgument(Expression* expr) {
3193 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
3194 for (
int i = 0; i < arguments->length(); i++) {
3200 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
3201 for (
int i = 0; i < exprs->length(); ++i) {
3208 graph_ =
new(zone())
HGraph(info());
3212 HPhase phase(
"H_Block building");
3217 Bailout(
"function with illegal redeclaration");
3221 Bailout(
"function calls eval");
3242 HBasicBlock* body_entry = CreateBasicBlock(initial_env);
3250 VisitVariableDeclaration(scope->
function());
3259 VisitStatements(info()->
function()->body());
3260 if (HasStackOverflow())
return NULL;
3273 ASSERT(unoptimized_code->kind() == Code::FUNCTION);
3274 Handle<Object> maybe_type_info(unoptimized_code->type_feedback_info());
3277 int checksum = type_info->own_type_change_checksum();
3280 !type_info->matches_inlined_type_change_checksum(composite_checksum));
3281 type_info->set_inlined_type_change_checksum(composite_checksum);
3300 "Unsupported phi use of const variable"));
3306 "Unsupported phi use of arguments"));
3314 for (
int j = 0; j < phis->length(); j++) {
3320 HInferRepresentation rep(
this);
3337 HPhase phase(
"H_Global value numbering",
this);
3338 HGlobalValueNumberer gvn(
this,
info());
3339 bool removed_side_effects = gvn.Analyze();
3343 if (FLAG_smi_only_arrays && removed_side_effects) {
3344 removed_side_effects = gvn.Analyze();
3345 ASSERT(!removed_side_effects);
3349 if (FLAG_use_range) {
3350 HRangeAnalysis rangeAnalysis(
this);
3351 rangeAnalysis.Analyze();
3356 HStackCheckEliminator sce(
this);
3382 return static_cast<uint32_t
>(index_base_->
Hashcode() ^ length_->
Hashcode());
3392 bool is_sub =
false;
3394 if (check->
index()->IsAdd()) {
3396 if (index->
left()->IsConstant()) {
3398 index_base = index->
right();
3399 }
else if (index->
right()->IsConstant()) {
3401 index_base = index->
left();
3403 }
else if (check->
index()->IsSub()) {
3406 if (index->
left()->IsConstant()) {
3408 index_base = index->
right();
3409 }
else if (index->
right()->IsConstant()) {
3411 index_base = index->
left();
3420 index_base = check->
index();
3428 : index_base_(index_base),
3431 HValue* index_base_;
3482 bool keep_new_check =
false;
3484 if (new_offset > upper_offset_) {
3485 upper_offset_ = new_offset;
3487 keep_new_check =
true;
3488 upper_check_ = new_check;
3490 BuildOffsetAdd(upper_check_,
3491 &added_upper_index_,
3492 &added_upper_offset_,
3498 }
else if (new_offset < lower_offset_) {
3499 lower_offset_ = new_offset;
3501 keep_new_check =
true;
3502 lower_check_ = new_check;
3504 BuildOffsetAdd(lower_check_,
3505 &added_lower_index_,
3506 &added_lower_offset_,
3516 if (!keep_new_check) {
3522 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_);
3523 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_);
3535 lower_offset_(lower_offset),
3536 upper_offset_(upper_offset),
3538 lower_check_(lower_check),
3539 upper_check_(upper_check),
3540 added_lower_index_(
NULL),
3541 added_lower_offset_(
NULL),
3542 added_upper_index_(
NULL),
3543 added_upper_offset_(
NULL),
3544 next_in_bb_(next_in_bb),
3545 father_in_dt_(father_in_dt) { }
3554 HAdd* added_lower_index_;
3556 HAdd* added_upper_index_;
3578 (*add)->InsertBefore(check);
3581 (*constant)->DeleteAndReplaceWith(new_constant);
3583 *constant = new_constant;
3586 void RemoveZeroAdd(HAdd** add, HConstant** constant) {
3587 if (*add !=
NULL && (*constant)->Integer32Value() == 0) {
3589 (*constant)->DeleteAndReplaceWith(
NULL);
3595 static bool BoundsCheckKeyMatch(
void* key1,
void* key2) {
3596 BoundsCheckKey* k1 =
static_cast<BoundsCheckKey*
>(key1);
3597 BoundsCheckKey* k2 =
static_cast<BoundsCheckKey*
>(key2);
3598 return k1->IndexBase() == k2->IndexBase() && k1->Length() == k2->Length();
3629 BoundsCheckTable* table) {
3630 BoundsCheckBbData* bb_data_list =
NULL;
3632 for (HInstruction* i = bb->first(); i !=
NULL; i = i->next()) {
3633 if (!i->IsBoundsCheck())
continue;
3636 check->ReplaceAllUsesWith(check->index());
3638 if (!FLAG_array_bounds_checks_elimination)
continue;
3641 BoundsCheckKey* key =
3643 if (key ==
NULL)
continue;
3644 BoundsCheckBbData** data_p = table->LookupOrInsert(key,
zone());
3645 BoundsCheckBbData* data = *data_p;
3647 bb_data_list =
new(
zone()) BoundsCheckBbData(key,
3655 *data_p = bb_data_list;
3656 }
else if (data->OffsetIsCovered(offset)) {
3657 check->DeleteAndReplaceWith(
NULL);
3658 }
else if (data->BasicBlock() == bb) {
3659 data->CoverCheck(check, offset);
3661 int32_t new_lower_offset = offset < data->LowerOffset()
3663 : data->LowerOffset();
3664 int32_t new_upper_offset = offset > data->UpperOffset()
3666 : data->UpperOffset();
3667 bb_data_list =
new(
zone()) BoundsCheckBbData(key,
3675 table->Insert(key, bb_data_list,
zone());
3679 for (
int i = 0; i < bb->dominated_blocks()->length(); ++i) {
3683 for (BoundsCheckBbData* data = bb_data_list;
3685 data = data->NextInBasicBlock()) {
3686 data->RemoveZeroOperations();
3687 if (data->FatherInDominatorTree()) {
3688 table->Insert(data->Key(), data->FatherInDominatorTree(),
zone());
3690 table->Delete(data->Key());
3697 HPhase phase(
"H_Eliminate bounds checks",
this);
3710 if (index->IsAdd()) {
3713 if (add->
left()->IsConstant()) {
3714 subexpression = add->
right();
3716 }
else if (add->
right()->IsConstant()) {
3717 subexpression = add->
left();
3722 }
else if (index->IsSub()) {
3725 if (sub->left()->IsConstant()) {
3726 subexpression = sub->right();
3728 }
else if (sub->right()->IsConstant()) {
3729 subexpression = sub->left();
3740 if (value >= 1 << 30 || value < 0)
return;
3741 array_operation->
SetKey(subexpression);
3752 if (!FLAG_array_index_dehoisting)
return;
3754 HPhase phase(
"H_Dehoist index computations",
this);
3755 for (
int i = 0; i <
blocks()->length(); ++i) {
3758 instr = instr->next()) {
3760 if (instr->IsLoadKeyedFastElement()) {
3763 }
else if (instr->IsLoadKeyedFastDoubleElement()) {
3767 }
else if (instr->IsLoadKeyedSpecializedArrayElement()) {
3771 }
else if (instr->IsStoreKeyedFastElement()) {
3774 }
else if (instr->IsStoreKeyedFastDoubleElement()) {
3778 }
else if (instr->IsStoreKeyedSpecializedArrayElement()) {
3785 DehoistArrayIndex(array_instruction);
3792 HPhase phase(
"H_Dead code elimination",
this);
3794 for (
int i = 0; i <
blocks()->length(); ++i) {
3797 instr = instr->next()) {
3798 if (instr->IsDead()) worklist.
Add(instr, zone());
3802 while (!worklist.is_empty()) {
3804 if (FLAG_trace_dead_code_elimination) {
3834 void HGraphBuilder::AddPhi(
HPhi* instr) {
3840 void HGraphBuilder::PushAndAdd(HInstruction* instr) {
3846 template <
class Instruction>
3847 HInstruction* HGraphBuilder::PreProcessCall(Instruction* call) {
3848 int count = call->argument_count();
3849 ZoneList<HValue*> arguments(count, zone());
3850 for (
int i = 0; i < count; ++i) {
3851 arguments.Add(
Pop(), zone());
3854 while (!arguments.is_empty()) {
3855 AddInstruction(
new(zone()) HPushArgument(arguments.RemoveLast()));
3861 void HGraphBuilder::SetUpScope(Scope* scope) {
3862 HConstant* undefined_constant =
new(zone()) HConstant(
3867 HArgumentsObject*
object =
new(zone()) HArgumentsObject;
3876 HInstruction* parameter =
AddInstruction(
new(zone()) HParameter(i));
3885 for (
int i =
environment()->parameter_count() + 1;
3893 if (scope->arguments() !=
NULL) {
3894 if (!scope->arguments()->IsStackAllocated()) {
3895 return Bailout(
"context-allocated arguments");
3904 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
3905 for (
int i = 0; i < statements->length(); i++) {
3911 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
3918 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
3921 header->SetInitialEnvironment(entry_env);
3922 header->AttachLoopInformation();
3927 void HGraphBuilder::VisitBlock(
Block* stmt) {
3928 ASSERT(!HasStackOverflow());
3931 if (stmt->scope() !=
NULL) {
3932 return Bailout(
"ScopedBlock");
3934 BreakAndContinueInfo break_info(stmt);
3935 { BreakAndContinueScope push(&break_info,
this);
3938 HBasicBlock* break_block = break_info.break_block();
3939 if (break_block !=
NULL) {
3941 break_block->SetJoinId(stmt->ExitId());
3947 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
3948 ASSERT(!HasStackOverflow());
3951 VisitForEffect(stmt->expression());
3955 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
3956 ASSERT(!HasStackOverflow());
3962 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
3963 ASSERT(!HasStackOverflow());
3966 if (stmt->condition()->ToBooleanIsTrue()) {
3968 Visit(stmt->then_statement());
3969 }
else if (stmt->condition()->ToBooleanIsFalse()) {
3971 Visit(stmt->else_statement());
3975 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
3977 if (cond_true->HasPredecessor()) {
3978 cond_true->SetJoinId(stmt->ThenId());
3986 if (cond_false->HasPredecessor()) {
3987 cond_false->SetJoinId(stmt->ElseId());
3995 HBasicBlock* join =
CreateJoin(cond_true, cond_false, stmt->IfId());
4001 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get(
4002 BreakableStatement* stmt,
4006 BreakAndContinueScope* current =
this;
4007 while (current !=
NULL && current->info()->target() != stmt) {
4008 *drop_extra += current->info()->drop_extra();
4009 current = current->next();
4013 if (type ==
BREAK) {
4014 *drop_extra += current->info()->drop_extra();
4017 HBasicBlock* block =
NULL;
4020 block = current->info()->break_block();
4021 if (block ==
NULL) {
4022 block = current->owner()->graph()->CreateBasicBlock();
4023 current->info()->set_break_block(block);
4028 block = current->info()->continue_block();
4029 if (block ==
NULL) {
4030 block = current->owner()->graph()->CreateBasicBlock();
4031 current->info()->set_continue_block(block);
4040 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
4041 ASSERT(!HasStackOverflow());
4045 HBasicBlock* continue_block =
break_scope()->Get(stmt->target(),
4054 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
4055 ASSERT(!HasStackOverflow());
4059 HBasicBlock* break_block =
break_scope()->Get(stmt->target(),
4068 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
4069 ASSERT(!HasStackOverflow());
4074 if (context ==
NULL) {
4083 if (context->IsTest()) {
4087 }
else if (context->IsEffect()) {
4091 ASSERT(context->IsValue());
4093 HValue* return_value =
Pop();
4095 HHasInstanceTypeAndBranch* typecheck =
4096 new(zone()) HHasInstanceTypeAndBranch(return_value,
4101 typecheck->SetSuccessorAt(0, if_spec_object);
4102 typecheck->SetSuccessorAt(1, not_spec_object);
4104 if_spec_object->AddLeaveInlined(return_value, state);
4105 not_spec_object->AddLeaveInlined(receiver, state);
4111 if (context->IsTest()) {
4113 context->ReturnValue(rhs);
4114 }
else if (context->IsEffect()) {
4117 ASSERT(context->IsValue());
4124 if (context->IsTest()) {
4126 VisitForControl(stmt->expression(), test->if_true(), test->if_false());
4127 }
else if (context->IsEffect()) {
4131 ASSERT(context->IsValue());
4140 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
4141 ASSERT(!HasStackOverflow());
4144 return Bailout(
"WithStatement");
4148 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
4149 ASSERT(!HasStackOverflow());
4154 const int kCaseClauseLimit = 128;
4155 ZoneList<CaseClause*>* clauses = stmt->cases();
4156 int clause_count = clauses->length();
4157 if (clause_count > kCaseClauseLimit) {
4158 return Bailout(
"SwitchStatement: too many clauses");
4165 HValue* tag_value =
Pop();
4171 for (
int i = 0; i < clause_count; ++i) {
4172 CaseClause* clause = clauses->at(i);
4173 if (clause->is_default())
continue;
4176 if (clause->label()->IsSmiLiteral()) {
4178 }
else if (clause->label()->IsStringLiteral()) {
4181 return Bailout(
"SwitchStatement: non-literal switch label");
4184 !clause->label()->IsStringLiteral()) ||
4186 !clause->label()->IsSmiLiteral())) {
4187 return Bailout(
"SwitchStatemnt: mixed label types are not supported");
4191 HUnaryControlInstruction* string_check =
NULL;
4192 HBasicBlock* not_string_block =
NULL;
4196 string_check =
new(zone()) HIsStringAndBranch(tag_value);
4200 string_check->SetSuccessorAt(0, first_test_block);
4201 string_check->SetSuccessorAt(1, not_string_block);
4209 for (
int i = 0; i < clause_count; ++i) {
4210 CaseClause* clause = clauses->at(i);
4211 if (clause->is_default()) {
4212 default_id = clause->EntryId();
4216 clause->RecordTypeFeedback(
oracle());
4221 HValue* label_value =
Pop();
4226 HControlInstruction* compare;
4229 if (!clause->IsSmiCompare()) {
4237 HCompareIDAndBranch* compare_ =
4238 new(zone()) HCompareIDAndBranch(tag_value,
4244 compare =
new(zone()) HStringCompareAndBranch(context, tag_value,
4249 compare->SetSuccessorAt(0, body_block);
4250 compare->SetSuccessorAt(1, next_test_block);
4260 if (not_string_block !=
NULL) {
4261 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId();
4262 last_block =
CreateJoin(last_block, not_string_block, join_id);
4267 HBasicBlock* curr_test_block = first_test_block;
4268 HBasicBlock* fall_through_block =
NULL;
4270 BreakAndContinueInfo break_info(stmt);
4271 { BreakAndContinueScope push(&break_info,
this);
4272 for (
int i = 0; i < clause_count; ++i) {
4273 CaseClause* clause = clauses->at(i);
4277 HBasicBlock* normal_block =
NULL;
4278 if (clause->is_default()) {
4279 if (last_block !=
NULL) {
4280 normal_block = last_block;
4283 }
else if (!curr_test_block->end()->IsDeoptimize()) {
4284 normal_block = curr_test_block->end()->FirstSuccessor();
4285 curr_test_block = curr_test_block->end()->SecondSuccessor();
4289 if (normal_block ==
NULL) {
4290 if (fall_through_block ==
NULL) {
4292 if (clause->is_default()) {
4301 }
else if (fall_through_block ==
NULL) {
4306 HBasicBlock* join =
CreateJoin(fall_through_block,
4319 HBasicBlock* break_block = break_info.break_block();
4320 if (break_block ==
NULL) {
4325 if (fall_through_block !=
NULL) fall_through_block->Goto(break_block);
4326 if (last_block !=
NULL) last_block->Goto(break_block);
4327 break_block->SetJoinId(stmt->ExitId());
4333 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
4334 return statement->OsrEntryId() == info()->
osr_ast_id();
4338 bool HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
4339 if (!HasOsrEntryAt(statement))
return false;
4344 HBranch* test =
new(zone()) HBranch(true_value, non_osr_entry, osr_entry);
4348 non_osr_entry->
Goto(loop_predecessor);
4351 BailoutId osr_entry_id = statement->OsrEntryId();
4354 ZoneList<HUnknownOSRValue*>* osr_values =
4355 new(zone()) ZoneList<HUnknownOSRValue*>(length, zone());
4357 for (
int i = 0; i < first_expression_index; ++i) {
4358 HUnknownOSRValue* osr_value =
new(zone()) HUnknownOSRValue;
4361 osr_values->Add(osr_value, zone());
4364 if (first_expression_index != length) {
4366 for (
int i = first_expression_index; i < length; ++i) {
4367 HUnknownOSRValue* osr_value =
new(zone()) HUnknownOSRValue;
4370 osr_values->Add(osr_value, zone());
4378 HContext* context =
new(zone()) HContext;
4382 loop_predecessor->SetJoinId(statement->EntryId());
4388 void HGraphBuilder::VisitLoopBody(IterationStatement* stmt,
4389 HBasicBlock* loop_entry,
4390 BreakAndContinueInfo* break_info) {
4391 BreakAndContinueScope push(break_info,
this);
4394 HStackCheck* stack_check =
4397 ASSERT(loop_entry->IsLoopHeader());
4398 loop_entry->loop_information()->set_stack_check(stack_check);
4403 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
4404 ASSERT(!HasStackOverflow());
4408 bool osr_entry = PreProcessOsrEntry(stmt);
4409 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
4414 BreakAndContinueInfo break_info(stmt);
4415 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
4416 HBasicBlock* body_exit =
4417 JoinContinue(stmt,
current_block(), break_info.continue_block());
4418 HBasicBlock* loop_successor =
NULL;
4419 if (body_exit !=
NULL && !stmt->cond()->ToBooleanIsTrue()) {
4425 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
4426 if (body_exit->HasPredecessor()) {
4427 body_exit->SetJoinId(stmt->BackEdgeId());
4431 if (loop_successor->HasPredecessor()) {
4432 loop_successor->SetJoinId(stmt->ExitId());
4434 loop_successor =
NULL;
4437 HBasicBlock* loop_exit = CreateLoop(stmt,
4441 break_info.break_block());
4446 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
4447 ASSERT(!HasStackOverflow());
4451 bool osr_entry = PreProcessOsrEntry(stmt);
4452 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
4459 HBasicBlock* loop_successor =
NULL;
4460 if (!stmt->cond()->ToBooleanIsTrue()) {
4463 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
4464 if (body_entry->HasPredecessor()) {
4465 body_entry->SetJoinId(stmt->BodyId());
4468 if (loop_successor->HasPredecessor()) {
4469 loop_successor->SetJoinId(stmt->ExitId());
4471 loop_successor =
NULL;
4475 BreakAndContinueInfo break_info(stmt);
4477 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
4479 HBasicBlock* body_exit =
4480 JoinContinue(stmt,
current_block(), break_info.continue_block());
4481 HBasicBlock* loop_exit = CreateLoop(stmt,
4485 break_info.break_block());
4490 void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
4491 ASSERT(!HasStackOverflow());
4494 if (stmt->init() !=
NULL) {
4498 bool osr_entry = PreProcessOsrEntry(stmt);
4499 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
4504 HBasicBlock* loop_successor =
NULL;
4505 if (stmt->cond() !=
NULL) {
4508 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
4509 if (body_entry->HasPredecessor()) {
4510 body_entry->SetJoinId(stmt->BodyId());
4513 if (loop_successor->HasPredecessor()) {
4514 loop_successor->SetJoinId(stmt->ExitId());
4516 loop_successor =
NULL;
4520 BreakAndContinueInfo break_info(stmt);
4522 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
4524 HBasicBlock* body_exit =
4525 JoinContinue(stmt,
current_block(), break_info.continue_block());
4527 if (stmt->next() !=
NULL && body_exit !=
NULL) {
4533 HBasicBlock* loop_exit = CreateLoop(stmt,
4537 break_info.break_block());
4542 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
4543 ASSERT(!HasStackOverflow());
4547 if (!FLAG_optimize_for_in) {
4548 return Bailout(
"ForInStatement optimization is disabled");
4551 if (!
oracle()->IsForInFastCase(stmt)) {
4552 return Bailout(
"ForInStatement is not fast case");
4555 if (!stmt->each()->IsVariableProxy() ||
4556 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
4557 return Bailout(
"ForInStatement with non-local each variable");
4560 Variable* each_var = stmt->each()->AsVariableProxy()->var();
4563 HValue* enumerable = Top();
4570 new(zone()) HForInCacheArray(
4575 HInstruction* enum_length =
AddInstruction(
new(zone()) HMapEnumLength(map));
4577 HInstruction* start_index =
AddInstruction(
new(zone()) HConstant(
4586 new(zone()) HForInCacheArray(
4593 bool osr_entry = PreProcessOsrEntry(stmt);
4594 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
4603 HCompareIDAndBranch* compare_index =
4604 new(zone()) HCompareIDAndBranch(index, limit, Token::LT);
4610 compare_index->SetSuccessorAt(0, loop_body);
4611 compare_index->SetSuccessorAt(1, loop_successor);
4620 new(zone()) HLoadKeyedFastElement(
4631 Bind(each_var, key);
4633 BreakAndContinueInfo break_info(stmt, 5);
4634 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
4636 HBasicBlock* body_exit =
4637 JoinContinue(stmt,
current_block(), break_info.continue_block());
4639 if (body_exit !=
NULL) {
4642 HValue* current_index =
Pop();
4647 PushAndAdd(new_index);
4651 HBasicBlock* loop_exit = CreateLoop(stmt,
4655 break_info.break_block());
4661 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
4662 ASSERT(!HasStackOverflow());
4665 return Bailout(
"TryCatchStatement");
4669 void HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
4670 ASSERT(!HasStackOverflow());
4673 return Bailout(
"TryFinallyStatement");
4677 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
4678 ASSERT(!HasStackOverflow());
4681 return Bailout(
"DebuggerStatement");
4685 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
4686 Code* unoptimized_code, FunctionLiteral* expr) {
4687 int start_position = expr->start_position();
4688 RelocIterator it(unoptimized_code);
4689 for (;!it.done(); it.next()) {
4690 RelocInfo* rinfo = it.rinfo();
4691 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT)
continue;
4692 Object* obj = rinfo->target_object();
4693 if (obj->IsSharedFunctionInfo()) {
4695 if (shared->start_position() == start_position) {
4696 return Handle<SharedFunctionInfo>(shared);
4701 return Handle<SharedFunctionInfo>();
4705 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
4706 ASSERT(!HasStackOverflow());
4709 Handle<SharedFunctionInfo> shared_info =
4710 SearchSharedFunctionInfo(info()->shared_info()->
code(),
4712 if (shared_info.is_null()) {
4716 if (HasStackOverflow())
return;
4718 HFunctionLiteral* instr =
4719 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure());
4724 void HGraphBuilder::VisitSharedFunctionInfoLiteral(
4725 SharedFunctionInfoLiteral* expr) {
4726 ASSERT(!HasStackOverflow());
4729 return Bailout(
"SharedFunctionInfoLiteral");
4733 void HGraphBuilder::VisitConditional(Conditional* expr) {
4734 ASSERT(!HasStackOverflow());
4739 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
4743 if (cond_true->HasPredecessor()) {
4744 cond_true->SetJoinId(expr->ThenId());
4752 if (cond_false->HasPredecessor()) {
4753 cond_false->SetJoinId(expr->ElseId());
4761 if (!ast_context()->IsTest()) {
4762 HBasicBlock* join =
CreateJoin(cond_true, cond_false, expr->id());
4764 if (join !=
NULL && !ast_context()->IsEffect()) {
4771 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty(
4772 Variable* var, LookupResult* lookup,
bool is_store) {
4776 Handle<GlobalObject> global(info()->global_object());
4777 global->Lookup(*var->name(), lookup);
4778 if (!lookup->IsNormal() ||
4779 (is_store && lookup->IsReadOnly()) ||
4780 lookup->holder() != *global) {
4788 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
4789 ASSERT(var->IsContextSlot());
4792 while (length-- > 0) {
4793 HInstruction* context_instruction =
new(zone()) HOuterContext(context);
4795 context = context_instruction;
4801 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
4802 ASSERT(!HasStackOverflow());
4805 Variable* variable = expr->var();
4806 switch (variable->location()) {
4810 return Bailout(
"reference to global lexical variable");
4814 Handle<Object> constant_value =
4815 isolate()->factory()->GlobalConstantFor(variable->name());
4816 if (!constant_value.is_null()) {
4822 LookupResult lookup(isolate());
4823 GlobalPropertyAccess type =
4824 LookupGlobalProperty(variable, &lookup,
false);
4826 if (type == kUseCell &&
4827 info()->global_object()->IsAccessCheckNeeded()) {
4831 if (type == kUseCell) {
4832 Handle<GlobalObject> global(info()->global_object());
4833 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
4834 HLoadGlobalCell* instr =
4835 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
4839 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
4841 HLoadGlobalGeneric* instr =
4842 new(zone()) HLoadGlobalGeneric(context,
4846 instr->set_position(expr->position());
4854 if (value ==
graph()->GetConstantHole()) {
4856 variable->mode() !=
VAR);
4857 return Bailout(
"reference to uninitialized variable");
4863 HValue* context = BuildContextChainWalk(variable);
4864 HLoadContextSlot* instr =
new(zone()) HLoadContextSlot(context, variable);
4869 return Bailout(
"reference to a variable which requires dynamic lookup");
4874 void HGraphBuilder::VisitLiteral(Literal* expr) {
4875 ASSERT(!HasStackOverflow());
4884 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
4885 ASSERT(!HasStackOverflow());
4889 Handle<FixedArray> literals(closure->literals());
4892 HRegExpLiteral* instr =
new(zone()) HRegExpLiteral(context,
4896 expr->literal_index());
4901 static void LookupInPrototypes(Handle<Map> map,
4902 Handle<String> name,
4903 LookupResult* lookup) {
4904 while (map->prototype()->IsJSObject()) {
4906 if (!holder->HasFastProperties())
break;
4907 map = Handle<Map>(holder->map());
4908 map->LookupDescriptor(*holder, *name, lookup);
4909 if (lookup->IsFound())
return;
4919 static bool LookupAccessorPair(Handle<Map> map,
4920 Handle<String> name,
4921 Handle<AccessorPair>* accessors,
4922 Handle<JSObject>* holder) {
4923 LookupResult lookup(map->GetIsolate());
4926 map->LookupDescriptor(
NULL, *name, &lookup);
4927 if (lookup.IsPropertyCallbacks()) {
4928 Handle<Object> callback(lookup.GetValueFromMap(*map));
4929 if (!callback->IsAccessorPair())
return false;
4931 *holder = Handle<JSObject>();
4936 if (lookup.IsFound())
return false;
4939 LookupInPrototypes(map, name, &lookup);
4940 if (lookup.IsPropertyCallbacks()) {
4941 Handle<Object> callback(lookup.GetValue());
4942 if (!callback->IsAccessorPair())
return false;
4944 *holder = Handle<JSObject>(lookup.holder());
4953 static bool LookupGetter(Handle<Map> map,
4954 Handle<String> name,
4955 Handle<JSFunction>* getter,
4956 Handle<JSObject>* holder) {
4957 Handle<AccessorPair> accessors;
4958 if (LookupAccessorPair(map, name, &accessors, holder) &&
4959 accessors->getter()->IsJSFunction()) {
4967 static bool LookupSetter(Handle<Map> map,
4968 Handle<String> name,
4969 Handle<JSFunction>* setter,
4970 Handle<JSObject>* holder) {
4971 Handle<AccessorPair> accessors;
4972 if (LookupAccessorPair(map, name, &accessors, holder) &&
4973 accessors->setter()->IsJSFunction()) {
4984 static bool IsFastLiteral(Handle<JSObject> boilerplate,
4986 int* max_properties,
4988 ASSERT(max_depth >= 0 && *max_properties >= 0);
4989 if (max_depth == 0)
return false;
4991 Handle<FixedArrayBase> elements(boilerplate->elements());
4992 if (elements->length() > 0 &&
4993 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) {
4994 if (boilerplate->HasFastDoubleElements()) {
4996 }
else if (boilerplate->HasFastObjectElements()) {
4998 int length = elements->length();
4999 for (
int i = 0; i < length; i++) {
5000 if ((*max_properties)-- == 0)
return false;
5001 Handle<Object> value(fast_elements->get(i));
5002 if (value->IsJSObject()) {
5004 if (!IsFastLiteral(value_object,
5018 Handle<FixedArray> properties(boilerplate->properties());
5019 if (properties->length() > 0) {
5022 int nof = boilerplate->map()->inobject_properties();
5023 for (
int i = 0; i < nof; i++) {
5024 if ((*max_properties)-- == 0)
return false;
5025 Handle<Object> value(boilerplate->InObjectPropertyAt(i));
5026 if (value->IsJSObject()) {
5028 if (!IsFastLiteral(value_object,
5038 *total_size += boilerplate->map()->instance_size();
5043 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
5044 ASSERT(!HasStackOverflow());
5049 HInstruction* literal;
5054 Handle<Object> boilerplate(closure->literals()->get(expr->literal_index()));
5055 if (boilerplate->IsJSObject() &&
5056 IsFastLiteral(Handle<JSObject>::cast(boilerplate),
5061 literal =
new(zone()) HFastLiteral(context,
5064 expr->literal_index(),
5067 literal =
new(zone()) HObjectLiteral(context,
5068 expr->constant_properties(),
5069 expr->fast_elements(),
5070 expr->literal_index(),
5072 expr->has_function());
5077 PushAndAdd(literal);
5079 expr->CalculateEmitStore(zone());
5081 for (
int i = 0; i < expr->properties()->length(); i++) {
5082 ObjectLiteral::Property*
property = expr->properties()->at(i);
5083 if (property->IsCompileTimeValue())
continue;
5085 Literal* key =
property->key();
5086 Expression* value =
property->value();
5088 switch (property->kind()) {
5093 if (key->handle()->IsSymbol()) {
5094 if (property->emit_store()) {
5095 property->RecordTypeFeedback(
oracle());
5097 HValue* value =
Pop();
5098 Handle<Map> map =
property->GetReceiverType();
5099 Handle<String> name =
property->key()->AsPropertyName();
5100 HInstruction* store;
5101 if (map.is_null()) {
5103 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value));
5106 Handle<JSFunction> setter;
5107 Handle<JSObject> holder;
5108 ASSERT(!LookupSetter(map, name, &setter, &holder));
5110 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal,
5116 if (store->HasObservableSideEffects())
AddSimulate(key->id());
5126 return Bailout(
"Object literal with complex property");
5131 if (expr->has_function()) {
5137 HToFastProperties* result =
new(zone()) HToFastProperties(
Pop());
5146 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
5147 ASSERT(!HasStackOverflow());
5150 ZoneList<Expression*>* subexprs = expr->values();
5151 int length = subexprs->length();
5153 HInstruction* literal;
5155 Handle<FixedArray> literals(
environment()->closure()->literals());
5156 Handle<Object> raw_boilerplate(literals->get(expr->literal_index()));
5158 if (raw_boilerplate->IsUndefined()) {
5160 isolate(), literals, expr->constant_elements());
5161 if (raw_boilerplate.is_null()) {
5162 return Bailout(
"array boilerplate creation failed");
5164 literals->set(expr->literal_index(), *raw_boilerplate);
5166 isolate()->heap()->fixed_cow_array_map()) {
5167 isolate()->counters()->cow_arrays_created_runtime()->Increment();
5178 if (IsFastLiteral(boilerplate,
5182 literal =
new(zone()) HFastLiteral(context,
5185 expr->literal_index(),
5188 literal =
new(zone()) HArrayLiteral(context,
5191 expr->literal_index(),
5197 PushAndAdd(literal);
5199 HLoadElements* elements =
NULL;
5201 for (
int i = 0; i < length; i++) {
5202 Expression* subexpr = subexprs->at(i);
5208 HValue* value =
Pop();
5213 elements =
new(zone()) HLoadElements(literal, literal);
5220 switch (boilerplate_elements_kind) {
5232 boilerplate_elements_kind));
5236 AddInstruction(
new(zone()) HStoreKeyedFastDoubleElement(elements,
5252 static bool ComputeLoadStoreField(Handle<Map> type,
5253 Handle<String> name,
5254 LookupResult* lookup,
5257 type->LookupDescriptor(
NULL, *name, lookup);
5258 if (lookup->IsField())
return true;
5261 if (!is_store)
return false;
5265 type->LookupTransition(
NULL, *name, lookup);
5266 return lookup->IsTransitionToField(*type) &&
5267 (type->unused_property_fields() > 0);
5271 static int ComputeLoadStoreFieldIndex(Handle<Map> type,
5272 Handle<String> name,
5273 LookupResult* lookup) {
5274 ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type));
5275 if (lookup->IsField()) {
5276 return lookup->GetLocalFieldIndexFromMap(*type);
5278 Map* transition = lookup->GetTransitionMapFromMap(*type);
5279 return transition->PropertyIndexFor(*name) - type->inobject_properties();
5284 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue*
object,
5285 Handle<String> name,
5288 LookupResult* lookup,
5289 bool smi_and_map_check) {
5290 ASSERT(lookup->IsFound());
5291 if (smi_and_map_check) {
5299 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) {
5300 Object* proto = map->prototype();
5302 LookupResult proto_result(isolate());
5303 proto->Lookup(*name, &proto_result);
5304 if (proto_result.IsProperty()) {
5306 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) {
5307 Bailout(
"improper object on prototype chain for store");
5311 proto = proto_result.holder();
5314 while (proto->GetPrototype()->IsJSObject()) proto = proto->GetPrototype();
5315 ASSERT(proto->GetPrototype()->IsNull());
5317 ASSERT(proto->IsJSObject());
5323 int index = ComputeLoadStoreFieldIndex(map, name, lookup);
5324 bool is_in_object = index < 0;
5329 offset += map->instance_size();
5333 HStoreNamedField* instr =
5334 new(zone()) HStoreNamedField(
object, name, value, is_in_object, offset);
5335 if (lookup->IsTransitionToField(*map)) {
5336 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
5337 instr->set_transition(transition);
5340 instr->SetGVNFlag(kChangesMaps);
5346 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue*
object,
5347 Handle<String> name,
5350 return new(zone()) HStoreNamedGeneric(
5355 function_strict_mode_flag());
5359 HInstruction* HGraphBuilder::BuildCallSetter(HValue*
object,
5362 Handle<JSFunction> setter,
5363 Handle<JSObject> holder) {
5364 AddCheckConstantFunction(holder,
object, map,
true);
5367 return new(zone()) HCallConstantFunction(setter, 2);
5371 HInstruction* HGraphBuilder::BuildStoreNamedMonomorphic(HValue*
object,
5372 Handle<String> name,
5376 LookupResult lookup(isolate());
5377 if (ComputeLoadStoreField(map, name, &lookup,
true)) {
5379 return BuildStoreNamedField(
object, name, value, map, &lookup,
true);
5383 return BuildStoreNamedGeneric(
object, name, value);
5387 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
5389 SmallMapList* types,
5390 Handle<String> name) {
5392 int previous_field_offset = 0;
5393 bool previous_field_is_in_object =
false;
5394 bool is_monomorphic_field =
true;
5396 LookupResult lookup(isolate());
5397 for (
int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
5399 if (ComputeLoadStoreField(map, name, &lookup,
false)) {
5400 int index = ComputeLoadStoreFieldIndex(map, name, &lookup);
5401 bool is_in_object = index < 0;
5406 offset += map->instance_size();
5411 previous_field_offset = offset;
5412 previous_field_is_in_object = is_in_object;
5413 }
else if (is_monomorphic_field) {
5414 is_monomorphic_field = (offset == previous_field_offset) &&
5415 (is_in_object == previous_field_is_in_object);
5424 HInstruction* instr;
5425 if (count == types->length() && is_monomorphic_field) {
5427 instr = BuildLoadNamedField(
object, map, &lookup,
false);
5430 instr =
new(zone()) HLoadNamedFieldPolymorphic(context,
5437 instr->set_position(expr->position());
5442 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
5445 SmallMapList* types,
5446 Handle<String> name) {
5451 HBasicBlock* join =
NULL;
5452 for (
int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
5453 Handle<Map> map = types->at(i);
5454 LookupResult lookup(isolate());
5455 if (ComputeLoadStoreField(map, name, &lookup,
true)) {
5463 HCompareMap* compare =
5464 new(zone()) HCompareMap(
object, map, if_true, if_false);
5468 HInstruction* instr;
5470 BuildStoreNamedField(
object, name, value, map, &lookup,
false));
5471 instr->set_position(expr->position());
5474 if (!ast_context()->IsEffect())
Push(value);
5484 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5487 HInstruction* instr = BuildStoreNamedGeneric(
object, name, value);
5488 instr->set_position(expr->position());
5492 if (!ast_context()->IsEffect())
Push(value);
5498 if (instr->HasObservableSideEffects()) {
5512 join->SetJoinId(expr->id());
5514 if (!ast_context()->IsEffect())
return ast_context()->
ReturnValue(
Pop());
5518 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
5519 Property* prop = expr->target()->AsProperty();
5521 expr->RecordTypeFeedback(
oracle(), zone());
5524 if (prop->key()->IsPropertyName()) {
5530 Literal* key = prop->key()->AsLiteral();
5534 HInstruction* instr =
NULL;
5535 SmallMapList* types = expr->GetReceiverTypes();
5536 bool monomorphic = expr->IsMonomorphic();
5539 map = types->first();
5540 if (map->is_dictionary_map()) monomorphic =
false;
5543 Handle<JSFunction> setter;
5544 Handle<JSObject> holder;
5545 if (LookupSetter(map, name, &setter, &holder)) {
5546 AddCheckConstantFunction(holder,
object, map,
true);
5547 if (FLAG_inline_accessors && TryInlineSetter(setter, expr, value)) {
5553 instr =
new(zone()) HCallConstantFunction(setter, 2);
5556 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(
object,
5562 }
else if (types !=
NULL && types->length() > 1) {
5564 return HandlePolymorphicStoreNamedField(expr,
object, value, types, name);
5567 instr = BuildStoreNamedGeneric(
object, name, value);
5571 instr->set_position(expr->position());
5573 if (instr->HasObservableSideEffects())
AddSimulate(expr->AssignmentId());
5580 HValue* value =
Pop();
5581 HValue* key =
Pop();
5582 HValue*
object =
Pop();
5583 bool has_side_effects =
false;
5584 HandleKeyedElementAccess(
object, key, value, expr, expr->AssignmentId(),
5589 ASSERT(has_side_effects);
5599 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
5603 LookupResult lookup(isolate());
5604 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup,
true);
5605 if (type == kUseCell) {
5606 Handle<GlobalObject> global(info()->global_object());
5607 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
5608 HInstruction* instr =
5609 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails());
5610 instr->set_position(position);
5612 if (instr->HasObservableSideEffects())
AddSimulate(ast_id);
5615 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
5617 HStoreGlobalGeneric* instr =
5618 new(zone()) HStoreGlobalGeneric(context,
5622 function_strict_mode_flag());
5623 instr->set_position(position);
5625 ASSERT(instr->HasObservableSideEffects());
5626 if (instr->HasObservableSideEffects())
AddSimulate(ast_id);
5631 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
5632 Expression* target = expr->target();
5633 VariableProxy* proxy = target->AsVariableProxy();
5634 Property* prop = target->AsProperty();
5639 BinaryOperation* operation = expr->binary_operation();
5641 if (proxy !=
NULL) {
5642 Variable* var = proxy->var();
5643 if (var->mode() ==
LET) {
5644 return Bailout(
"unsupported let compound assignment");
5649 switch (var->location()) {
5651 HandleGlobalVariableAssignment(var,
5654 expr->AssignmentId());
5659 if (var->mode() ==
CONST) {
5660 return Bailout(
"unsupported const compound assignment");
5669 if (info()->scope()->arguments() !=
NULL) {
5674 for (
int i = 0; i < count; ++i) {
5675 if (var == info()->scope()->parameter(i)) {
5677 "assignment to parameter, function uses arguments object");
5684 switch (var->mode()) {
5698 HValue* context = BuildContextChainWalk(var);
5699 HStoreContextSlot* instr =
5700 new(zone()) HStoreContextSlot(context, var->index(), mode, Top());
5702 if (instr->HasObservableSideEffects()) {
5709 return Bailout(
"compound assignment to lookup slot");
5713 }
else if (prop !=
NULL) {
5714 prop->RecordTypeFeedback(
oracle(), zone());
5716 if (prop->key()->IsPropertyName()) {
5719 HValue*
object = Top();
5721 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
5724 bool monomorphic = prop->IsMonomorphic();
5726 map = prop->GetReceiverTypes()->first();
5729 if (map->is_dictionary_map()) monomorphic =
false;
5732 Handle<JSFunction> getter;
5733 Handle<JSObject> holder;
5734 if (LookupGetter(map, name, &getter, &holder)) {
5735 load = BuildCallGetter(
object, map, getter, holder);
5737 load = BuildLoadNamedMonomorphic(
object, name, prop, map);
5740 load = BuildLoadNamedGeneric(
object, name, prop);
5743 if (load->HasObservableSideEffects())
AddSimulate(prop->LoadId());
5746 HValue* right =
Pop();
5747 HValue* left =
Pop();
5749 HInstruction* instr = BuildBinaryOperation(operation, left, right);
5751 if (instr->HasObservableSideEffects())
AddSimulate(operation->id());
5753 HInstruction* store;
5756 CHECK_ALIVE(store = BuildStoreNamedGeneric(
object, name, instr));
5758 Handle<JSFunction> setter;
5759 Handle<JSObject> holder;
5760 if (LookupSetter(map, name, &setter, &holder)) {
5761 store = BuildCallSetter(
object, instr, map, setter, holder);
5763 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(
object,
5773 if (store->HasObservableSideEffects())
AddSimulate(expr->AssignmentId());
5783 bool has_side_effects =
false;
5784 HValue* load = HandleKeyedElementAccess(
5785 obj, key,
NULL, prop, prop->LoadId(), RelocInfo::kNoPosition,
5789 if (has_side_effects)
AddSimulate(prop->LoadId());
5793 HValue* right =
Pop();
5794 HValue* left =
Pop();
5796 HInstruction* instr = BuildBinaryOperation(operation, left, right);
5798 if (instr->HasObservableSideEffects())
AddSimulate(operation->id());
5800 expr->RecordTypeFeedback(
oracle(), zone());
5801 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
5802 RelocInfo::kNoPosition,
5809 ASSERT(has_side_effects);
5815 return Bailout(
"invalid lhs in compound assignment");
5820 void HGraphBuilder::VisitAssignment(Assignment* expr) {
5821 ASSERT(!HasStackOverflow());
5824 VariableProxy* proxy = expr->target()->AsVariableProxy();
5825 Property* prop = expr->target()->AsProperty();
5828 if (expr->is_compound()) {
5829 HandleCompoundAssignment(expr);
5834 HandlePropertyAssignment(expr);
5835 }
else if (proxy !=
NULL) {
5836 Variable* var = proxy->var();
5838 if (var->mode() ==
CONST) {
5839 if (expr->op() != Token::INIT_CONST) {
5844 if (var->IsStackAllocated()) {
5851 if (expr->op() != Token::INIT_CONST_HARMONY) {
5852 return Bailout(
"non-initializer assignment to const");
5856 if (proxy->IsArguments())
return Bailout(
"assignment to arguments");
5859 switch (var->location()) {
5862 HandleGlobalVariableAssignment(var,
5865 expr->AssignmentId());
5872 if (var->mode() ==
LET && expr->op() == Token::ASSIGN) {
5874 if (env_value ==
graph()->GetConstantHole()) {
5875 return Bailout(
"assignment to let variable before initialization");
5882 HValue* value =
Pop();
5891 if (info()->scope()->arguments() !=
NULL) {
5895 for (
int i = 0; i < count; ++i) {
5896 if (var == info()->scope()->parameter(i)) {
5897 return Bailout(
"assignment to parameter in arguments object");
5904 if (expr->op() == Token::ASSIGN) {
5905 switch (var->mode()) {
5918 }
else if (expr->op() == Token::INIT_VAR ||
5919 expr->op() == Token::INIT_LET ||
5920 expr->op() == Token::INIT_CONST_HARMONY) {
5923 ASSERT(expr->op() == Token::INIT_CONST);
5928 HValue* context = BuildContextChainWalk(var);
5929 HStoreContextSlot* instr =
new(zone()) HStoreContextSlot(
5930 context, var->index(), mode, Top());
5932 if (instr->HasObservableSideEffects()) {
5939 return Bailout(
"assignment to LOOKUP variable");
5942 return Bailout(
"invalid left-hand side in assignment");
5947 void HGraphBuilder::VisitThrow(Throw* expr) {
5948 ASSERT(!HasStackOverflow());
5954 ASSERT(ast_context()->IsEffect());
5959 HThrow* instr =
new(zone()) HThrow(context, value);
5960 instr->set_position(expr->position());
5968 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue*
object,
5970 LookupResult* lookup,
5971 bool smi_and_map_check) {
5972 if (smi_and_map_check) {
5977 int index = lookup->GetLocalFieldIndexFromMap(*map);
5981 int offset = (index *
kPointerSize) + map->instance_size();
5982 return new(zone()) HLoadNamedField(
object,
true, offset);
5986 return new(zone()) HLoadNamedField(
object,
false, offset);
5991 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue*
object,
5992 Handle<String> name,
5994 if (expr->IsUninitialized() && !FLAG_always_opt) {
5999 return new(zone()) HLoadNamedGeneric(context,
object, name);
6003 HInstruction* HGraphBuilder::BuildCallGetter(HValue*
object,
6005 Handle<JSFunction> getter,
6006 Handle<JSObject> holder) {
6007 AddCheckConstantFunction(holder,
object, map,
true);
6009 return new(zone()) HCallConstantFunction(getter, 1);
6013 HInstruction* HGraphBuilder::BuildLoadNamedMonomorphic(HValue*
object,
6014 Handle<String> name,
6018 ASSERT(!map->is_dictionary_map());
6019 LookupResult lookup(isolate());
6020 map->LookupDescriptor(
NULL, *name, &lookup);
6021 if (lookup.IsField()) {
6022 return BuildLoadNamedField(
object, map, &lookup,
true);
6026 if (lookup.IsConstantFunction()) {
6029 Handle<JSFunction>
function(lookup.GetConstantFunctionFromMap(*map));
6034 return BuildLoadNamedGeneric(
object, name, expr);
6038 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue*
object,
6041 return new(zone()) HLoadKeyedGeneric(context,
object, key);
6045 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
6046 HValue* external_elements,
6047 HValue* checked_key,
6054 switch (elements_kind) {
6065 if (!val->representation().IsInteger32()) {
6088 return new(zone()) HStoreKeyedSpecializedArrayElement(
6089 external_elements, checked_key, val, elements_kind);
6092 HLoadKeyedSpecializedArrayElement* load =
6093 new(zone()) HLoadKeyedSpecializedArrayElement(
6094 external_elements, checked_key, dependency, elements_kind);
6095 if (FLAG_opt_safe_uint32_operations &&
6104 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
6105 HValue* checked_key,
6107 HValue* load_dependency,
6112 switch (elements_kind) {
6115 return new(zone()) HStoreKeyedFastDoubleElement(
6116 elements, checked_key, val);
6124 return new(zone()) HStoreKeyedFastElement(
6125 elements, checked_key, val, elements_kind);
6136 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key,
6137 load_dependency, mode);
6139 return new(zone()) HLoadKeyedFastElement(elements, checked_key,
6140 load_dependency, elements_kind);
6145 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue*
object,
6151 HCheckMaps* mapcheck =
new(zone()) HCheckMaps(
object, map,
6152 zone(), dependency);
6155 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
6157 return BuildUncheckedMonomorphicElementAccess(
object, key, val,
6158 mapcheck, map, is_store);
6162 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
6166 HCheckMaps* mapcheck,
6177 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
6179 bool fast_smi_only_elements = map->has_fast_smi_elements();
6180 bool fast_elements = map->has_fast_object_elements();
6181 HInstruction* elements =
6183 if (is_store && (fast_elements || fast_smi_only_elements)) {
6184 HCheckMaps* check_cow_map =
new(zone()) HCheckMaps(
6185 elements, isolate()->factory()->fixed_array_map(), zone());
6186 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
6189 HInstruction* length =
NULL;
6190 HInstruction* checked_key =
NULL;
6191 if (map->has_external_array_elements()) {
6192 length =
AddInstruction(
new(zone()) HFixedArrayBaseLength(elements));
6193 checked_key =
AddInstruction(
new(zone()) HBoundsCheck(key, length,
6195 HLoadExternalArrayPointer* external_elements =
6196 new(zone()) HLoadExternalArrayPointer(elements);
6198 return BuildExternalArrayElementAccess(
6199 external_elements, checked_key, val, mapcheck,
6200 map->elements_kind(), is_store);
6202 ASSERT(fast_smi_only_elements ||
6204 map->has_fast_double_elements());
6206 length =
AddInstruction(
new(zone()) HJSArrayLength(
object, mapcheck,
6209 length =
AddInstruction(
new(zone()) HFixedArrayBaseLength(elements));
6211 checked_key =
AddInstruction(
new(zone()) HBoundsCheck(key, length,
6213 return BuildFastElementAccess(elements, checked_key, val, mapcheck,
6214 map->elements_kind(), is_store);
6218 HInstruction* HGraphBuilder::TryBuildConsolidatedElementLoad(
6222 SmallMapList* maps) {
6227 bool has_double_maps =
false;
6228 bool has_smi_or_object_maps =
false;
6229 bool has_js_array_access =
false;
6230 bool has_non_js_array_access =
false;
6231 Handle<Map> most_general_consolidated_map;
6232 for (
int i = 0; i < maps->length(); ++i) {
6233 Handle<Map> map = maps->at(i);
6236 if (has_non_js_array_access)
return NULL;
6237 has_js_array_access =
true;
6238 }
else if (has_js_array_access) {
6241 has_non_js_array_access =
true;
6244 if (map->has_fast_double_elements()) {
6245 if (has_smi_or_object_maps)
return NULL;
6246 has_double_maps =
true;
6247 }
else if (map->has_fast_smi_or_object_elements()) {
6248 if (has_double_maps)
return NULL;
6249 has_smi_or_object_maps =
true;
6256 most_general_consolidated_map->elements_kind(),
6257 map->elements_kind())) {
6258 most_general_consolidated_map = map;
6261 if (!has_double_maps && !has_smi_or_object_maps)
return NULL;
6263 HCheckMaps* check_maps =
new(zone()) HCheckMaps(
object, maps, zone());
6265 HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
6266 object, key, val, check_maps, most_general_consolidated_map,
false);
6271 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue*
object,
6278 bool* has_side_effects) {
6279 *has_side_effects =
false;
6281 SmallMapList* maps = prop->GetReceiverTypes();
6282 bool todo_external_array =
false;
6285 HInstruction* consolidated_load =
6286 TryBuildConsolidatedElementLoad(
object, key, val, maps);
6287 if (consolidated_load !=
NULL) {
6289 *has_side_effects |= consolidated_load->HasObservableSideEffects();
6290 if (position != RelocInfo::kNoPosition) {
6291 consolidated_load->set_position(position);
6293 return consolidated_load;
6298 bool type_todo[kNumElementTypes];
6299 for (
int i = 0; i < kNumElementTypes; ++i) {
6300 type_todo[i] =
false;
6307 for (
int i = 0; i < maps->length(); ++i) {
6308 Handle<Map> map = maps->at(i);
6312 possible_transitioned_maps.Add(map);
6316 for (
int i = 0; i < maps->length(); ++i) {
6317 Handle<Map> map = maps->at(i);
6318 Handle<Map> transitioned_map =
6319 map->FindTransitionedMap(&possible_transitioned_maps);
6320 transition_target.Add(transitioned_map);
6323 int num_untransitionable_maps = 0;
6324 Handle<Map> untransitionable_map;
6325 HTransitionElementsKind* transition =
NULL;
6326 for (
int i = 0; i < maps->length(); ++i) {
6327 Handle<Map> map = maps->at(i);
6329 if (!transition_target.at(i).is_null()) {
6331 map->elements_kind(),
6332 transition_target.at(i)->elements_kind()));
6333 transition =
new(zone()) HTransitionElementsKind(
6334 object, map, transition_target.at(i));
6337 type_todo[map->elements_kind()] =
true;
6339 todo_external_array =
true;
6341 num_untransitionable_maps++;
6342 untransitionable_map = map;
6348 if (num_untransitionable_maps == 1) {
6349 HInstruction* instr =
NULL;
6350 if (untransitionable_map->has_slow_elements_kind()) {
6351 instr =
AddInstruction(is_store ? BuildStoreKeyedGeneric(
object, key, val)
6352 : BuildLoadKeyedGeneric(
object, key));
6355 object, key, val, transition, untransitionable_map, is_store));
6357 *has_side_effects |= instr->HasObservableSideEffects();
6358 if (position != RelocInfo::kNoPosition) instr->set_position(position);
6359 return is_store ?
NULL : instr;
6362 HInstruction* checkspec =
6366 HInstruction* elements_kind_instr =
6368 HCompareConstantEqAndBranch* elements_kind_branch =
NULL;
6369 HInstruction* elements =
6371 HLoadExternalArrayPointer* external_elements =
NULL;
6372 HInstruction* checked_key =
NULL;
6389 && todo_external_array) {
6390 HInstruction* length =
6392 checked_key =
AddInstruction(
new(zone()) HBoundsCheck(key, length));
6393 external_elements =
new(zone()) HLoadExternalArrayPointer(elements);
6396 if (type_todo[elements_kind]) {
6399 elements_kind_branch =
new(zone()) HCompareConstantEqAndBranch(
6400 elements_kind_instr, elements_kind, Token::EQ_STRICT);
6401 elements_kind_branch->SetSuccessorAt(0, if_true);
6402 elements_kind_branch->SetSuccessorAt(1, if_false);
6406 HInstruction* access;
6410 elements, isolate()->factory()->fixed_array_map(),
6411 zone(), elements_kind_branch));
6423 HHasInstanceTypeAndBranch* typecheck =
6424 new(zone()) HHasInstanceTypeAndBranch(
object,
JS_ARRAY_TYPE);
6425 typecheck->SetSuccessorAt(0, if_jsarray);
6426 typecheck->SetSuccessorAt(1, if_fastobject);
6430 HInstruction* length;
6431 length =
AddInstruction(
new(zone()) HJSArrayLength(
object, typecheck,
6433 checked_key =
AddInstruction(
new(zone()) HBoundsCheck(key, length,
6436 elements, checked_key, val, elements_kind_branch,
6437 elements_kind, is_store));
6442 *has_side_effects |= access->HasObservableSideEffects();
6443 if (position != -1) {
6444 access->set_position(position);
6446 if_jsarray->Goto(join);
6449 length =
AddInstruction(
new(zone()) HFixedArrayBaseLength(elements));
6450 checked_key =
AddInstruction(
new(zone()) HBoundsCheck(key, length,
6453 elements, checked_key, val, elements_kind_branch,
6454 elements_kind, is_store));
6457 access =
AddInstruction(BuildStoreKeyedGeneric(
object, key, val));
6463 external_elements, checked_key, val, elements_kind_branch,
6464 elements_kind, is_store));
6466 *has_side_effects |= access->HasObservableSideEffects();
6467 if (position != RelocInfo::kNoPosition) access->set_position(position);
6478 join->SetJoinId(ast_id);
6480 return is_store ?
NULL :
Pop();
6484 HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj,
6491 bool* has_side_effects) {
6492 ASSERT(!expr->IsPropertyName());
6493 HInstruction* instr =
NULL;
6494 if (expr->IsMonomorphic()) {
6495 Handle<Map> map = expr->GetMonomorphicReceiverType();
6496 if (map->has_slow_elements_kind()) {
6497 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
6498 : BuildLoadKeyedGeneric(obj, key);
6501 instr = BuildMonomorphicElementAccess(obj, key, val,
NULL, map, is_store);
6503 }
else if (expr->GetReceiverTypes() !=
NULL &&
6504 !expr->GetReceiverTypes()->is_empty()) {
6505 return HandlePolymorphicElementAccess(
6506 obj, key, val, expr, ast_id, position, is_store, has_side_effects);
6509 instr = BuildStoreKeyedGeneric(obj, key, val);
6511 instr = BuildLoadKeyedGeneric(obj, key);
6514 if (position != RelocInfo::kNoPosition) instr->set_position(position);
6516 *has_side_effects = instr->HasObservableSideEffects();
6521 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue*
object,
6525 return new(zone()) HStoreKeyedGeneric(
6530 function_strict_mode_flag());
6534 void HGraphBuilder::EnsureArgumentsArePushedForAccess() {
6544 ZoneList<HValue*>* arguments_values = entry->arguments_values();
6546 HInstruction* insert_after = entry;
6547 for (
int i = 0; i < arguments_values->length(); i++) {
6548 HValue* argument = arguments_values->at(i);
6549 HInstruction* push_argument =
new(zone()) HPushArgument(argument);
6550 push_argument->InsertAfter(insert_after);
6551 insert_after = push_argument;
6554 HArgumentsElements* arguments_elements =
6555 new(zone()) HArgumentsElements(
true);
6557 arguments_elements->InsertAfter(insert_after);
6562 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
6563 VariableProxy* proxy = expr->obj()->AsVariableProxy();
6564 if (proxy ==
NULL)
return false;
6565 if (!proxy->var()->IsStackAllocated())
return false;
6570 HInstruction* result =
NULL;
6571 if (expr->key()->IsPropertyName()) {
6572 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
6573 if (!name->IsEqualTo(
CStrVector(
"length")))
return false;
6577 new(zone()) HArgumentsElements(
false));
6578 result =
new(zone()) HArgumentsLength(elements);
6583 result =
new(zone()) HConstant(
6589 VisitForValue(expr->key());
6591 HValue* key =
Pop();
6595 new(zone()) HArgumentsElements(
false));
6597 new(zone()) HArgumentsLength(elements));
6598 HInstruction* checked_key =
6600 result =
new(zone()) HAccessArgumentsAt(elements, length, checked_key);
6602 EnsureArgumentsArePushedForAccess();
6611 HInstruction* checked_key =
6613 result =
new(zone()) HAccessArgumentsAt(elements, length, checked_key);
6621 void HGraphBuilder::VisitProperty(Property* expr) {
6622 ASSERT(!HasStackOverflow());
6625 expr->RecordTypeFeedback(
oracle(), zone());
6627 if (TryArgumentsAccess(expr))
return;
6631 HInstruction* instr =
NULL;
6632 if (expr->AsProperty()->IsArrayLength()) {
6633 HValue* array =
Pop();
6635 HInstruction* mapcheck =
6637 instr =
new(zone()) HJSArrayLength(array, mapcheck);
6638 }
else if (expr->IsStringLength()) {
6639 HValue*
string =
Pop();
6642 instr =
new(zone()) HStringLength(
string);
6643 }
else if (expr->IsStringAccess()) {
6645 HValue* index =
Pop();
6646 HValue*
string =
Pop();
6648 HStringCharCodeAt* char_code =
6649 BuildStringCharCodeAt(context,
string, index);
6651 instr =
new(zone()) HStringCharFromCode(context, char_code);
6653 }
else if (expr->IsFunctionPrototype()) {
6654 HValue*
function =
Pop();
6656 instr =
new(zone()) HLoadFunctionPrototype(
function);
6658 }
else if (expr->key()->IsPropertyName()) {
6659 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
6660 SmallMapList* types = expr->GetReceiverTypes();
6662 bool monomorphic = expr->IsMonomorphic();
6664 if (expr->IsMonomorphic()) {
6665 map = types->first();
6666 if (map->is_dictionary_map()) monomorphic =
false;
6669 Handle<JSFunction> getter;
6670 Handle<JSObject> holder;
6671 if (LookupGetter(map, name, &getter, &holder)) {
6672 AddCheckConstantFunction(holder, Top(), map,
true);
6673 if (FLAG_inline_accessors && TryInlineGetter(getter, expr))
return;
6675 instr =
new(zone()) HCallConstantFunction(getter, 1);
6677 instr = BuildLoadNamedMonomorphic(
Pop(), name, expr, map);
6679 }
else if (types !=
NULL && types->length() > 1) {
6680 return HandlePolymorphicLoadNamedField(expr,
Pop(), types, name);
6682 instr = BuildLoadNamedGeneric(
Pop(), name, expr);
6688 HValue* key =
Pop();
6689 HValue* obj =
Pop();
6691 bool has_side_effects =
false;
6692 HValue* load = HandleKeyedElementAccess(
6693 obj, key,
NULL, expr, expr->id(), expr->position(),
6696 if (has_side_effects) {
6707 instr->set_position(expr->position());
6712 void HGraphBuilder::AddCheckConstantFunction(Handle<JSObject> holder,
6714 Handle<Map> receiver_map,
6715 bool smi_and_map_check) {
6719 if (smi_and_map_check) {
6724 if (!holder.is_null()) {
6726 Handle<JSObject>(
JSObject::cast(receiver_map->prototype())), holder));
6737 ast_length_(ast_length),
6738 src_length_(src_length) { }
6753 static int CompareHotness(
void const* a,
void const* b) {
6754 FunctionSorter
const* function1 =
reinterpret_cast<FunctionSorter const*
>(a);
6755 FunctionSorter
const* function2 =
reinterpret_cast<FunctionSorter const*
>(b);
6756 int diff = function1->ticks() - function2->ticks();
6757 if (diff != 0)
return -diff;
6758 diff = function1->ast_length() - function2->ast_length();
6759 if (diff != 0)
return diff;
6760 return function1->src_length() - function2->src_length();
6764 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
6766 SmallMapList* types,
6767 Handle<String> name) {
6771 int argument_count = expr->arguments()->length() + 1;
6772 HBasicBlock* join =
NULL;
6773 FunctionSorter order[kMaxCallPolymorphism];
6774 int ordered_functions = 0;
6776 i < types->length() && ordered_functions < kMaxCallPolymorphism;
6778 Handle<Map> map = types->at(i);
6779 if (expr->ComputeTarget(map, name)) {
6780 order[ordered_functions++] =
6782 expr->target()->shared()->profiler_ticks(),
6783 InliningAstSize(expr->target()),
6784 expr->target()->shared()->SourceSize());
6788 qsort(reinterpret_cast<void*>(&order[0]),
6793 for (
int fn = 0; fn < ordered_functions; ++fn) {
6794 int i = order[fn].index();
6795 Handle<Map> map = types->at(i);
6803 HCompareMap* compare =
6804 new(zone()) HCompareMap(receiver, map, if_true, if_false);
6808 expr->ComputeTarget(map, name);
6809 AddCheckConstantFunction(expr->holder(), receiver, map,
false);
6810 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
6811 Handle<JSFunction> caller = info()->
closure();
6812 SmartArrayPointer<char> caller_name =
6813 caller->shared()->DebugName()->ToCString();
6814 PrintF(
"Trying to inline the polymorphic call to %s from %s\n",
6818 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) {
6821 if (HasStackOverflow())
return;
6823 HCallConstantFunction* call =
6824 new(zone()) HCallConstantFunction(expr->target(), argument_count);
6825 call->set_position(expr->position());
6826 PreProcessCall(call);
6828 if (!ast_context()->IsEffect())
Push(call);
6838 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
6842 HCallNamed* call =
new(zone()) HCallNamed(context, name, argument_count);
6843 call->set_position(expr->position());
6844 PreProcessCall(call);
6848 if (!ast_context()->IsEffect())
Push(call);
6859 if (join->HasPredecessor()) {
6861 join->SetJoinId(expr->id());
6869 void HGraphBuilder::TraceInline(Handle<JSFunction> target,
6870 Handle<JSFunction> caller,
6871 const char* reason) {
6872 if (FLAG_trace_inlining) {
6873 SmartArrayPointer<char> target_name =
6874 target->shared()->DebugName()->ToCString();
6875 SmartArrayPointer<char> caller_name =
6876 caller->shared()->DebugName()->ToCString();
6877 if (reason ==
NULL) {
6878 PrintF(
"Inlined %s called from %s.\n", *target_name, *caller_name);
6880 PrintF(
"Did not inline %s called from %s (%s).\n",
6881 *target_name, *caller_name, reason);
6887 static const int kNotInlinable = 1000000000;
6890 int HGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
6891 if (!FLAG_use_inlining)
return kNotInlinable;
6895 Handle<JSFunction> caller = info()->
closure();
6896 Handle<SharedFunctionInfo> target_shared(target->shared());
6900 if (target_shared->SourceSize() >
6901 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
6902 TraceInline(target, caller,
"target text too big");
6903 return kNotInlinable;
6907 if (!target->IsInlineable()) {
6908 TraceInline(target, caller,
"target not inlineable");
6909 return kNotInlinable;
6911 if (target_shared->dont_inline() || target_shared->dont_optimize()) {
6912 TraceInline(target, caller,
"target contains unsupported syntax [early]");
6913 return kNotInlinable;
6916 int nodes_added = target_shared->ast_node_count();
6921 bool HGraphBuilder::TryInline(
CallKind call_kind,
6922 Handle<JSFunction> target,
6923 int arguments_count,
6924 HValue* implicit_return_value,
6926 BailoutId return_id,
6928 int nodes_added = InliningAstSize(target);
6929 if (nodes_added == kNotInlinable)
return false;
6931 Handle<JSFunction> caller = info()->
closure();
6933 if (nodes_added >
Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
6934 TraceInline(target, caller,
"target AST is too large [early]");
6938 Handle<SharedFunctionInfo> target_shared(target->shared());
6940 #if !defined(V8_TARGET_ARCH_IA32)
6942 CompilationInfo* outer_info = info();
6943 if (target->context() != outer_info->closure()->context() ||
6944 outer_info->scope()->contains_with() ||
6945 outer_info->scope()->num_heap_slots() > 0) {
6946 TraceInline(target, caller,
"target requires context change");
6954 int current_level = 1;
6955 while (env->outer() !=
NULL) {
6957 TraceInline(target, caller,
"inline depth limit reached");
6969 state = state->outer()) {
6970 if (state->compilation_info()->closure()->shared() == *target_shared) {
6971 TraceInline(target, caller,
"target is recursive");
6977 if (inlined_count_ >
Min(FLAG_max_inlined_nodes_cumulative,
6978 kUnlimitedMaxInlinedNodesCumulative)) {
6979 TraceInline(target, caller,
"cumulative AST node limit reached");
6984 CompilationInfo target_info(target, zone());
6987 if (target_info.isolate()->has_pending_exception()) {
6990 target_shared->DisableOptimization(
"parse/scope error");
6992 TraceInline(target, caller,
"parse failure");
6996 if (target_info.scope()->num_heap_slots() > 0) {
6997 TraceInline(target, caller,
"target has context-allocated variables");
7000 FunctionLiteral*
function = target_info.function();
7004 nodes_added =
function->ast_node_count();
7005 if (nodes_added >
Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
7006 TraceInline(target, caller,
"target AST is too large [late]");
7009 AstProperties::Flags*
flags(function->flags());
7011 TraceInline(target, caller,
"target contains unsupported syntax [late]");
7018 if (function->scope()->arguments() !=
NULL) {
7019 if (!FLAG_inline_arguments) {
7020 TraceInline(target, caller,
"target uses arguments object");
7024 if (!function->scope()->arguments()->IsStackAllocated()) {
7027 "target uses non-stackallocated arguments object");
7033 ZoneList<Declaration*>* decls = target_info.scope()->declarations();
7034 int decl_count = decls->length();
7035 for (
int i = 0; i < decl_count; ++i) {
7036 if (!decls->at(i)->IsInlineable()) {
7037 TraceInline(target, caller,
"target has non-trivial declaration");
7044 if (!target_shared->has_deoptimization_support()) {
7047 target_info.EnableDeoptimizationSupport();
7049 TraceInline(target, caller,
"could not generate deoptimization info");
7055 Handle<ScopeInfo> target_scope_info =
7057 target_shared->set_scope_info(*target_scope_info);
7059 target_shared->EnableDeoptimizationSupport(*target_info.code());
7071 ASSERT(target_shared->has_deoptimization_support());
7072 Handle<Code> unoptimized_code(target_shared->code());
7073 TypeFeedbackOracle target_oracle(
7075 Handle<Context>(target->context()->native_context()),
7081 this, &target_info, &target_oracle, inlining_kind);
7084 HEnvironment* inner_env =
7091 #ifdef V8_TARGET_ARCH_IA32
7097 HConstant* context =
7098 new(zone()) HConstant(Handle<Context>(target->context()),
7101 inner_env->BindContext(context);
7107 ZoneList<HValue*>* arguments_values =
NULL;
7111 if (function->scope()->arguments() !=
NULL) {
7112 HEnvironment* arguments_env = inner_env->arguments_environment();
7113 int arguments_count = arguments_env->parameter_count();
7114 arguments_values =
new(zone()) ZoneList<HValue*>(arguments_count, zone());
7115 for (
int i = 0; i < arguments_count; i++) {
7116 arguments_values->Add(arguments_env->Lookup(i), zone());
7120 HEnterInlined* enter_inlined =
7121 new(zone()) HEnterInlined(target,
7126 function->scope()->arguments(),
7132 if (function->scope()->arguments() !=
NULL) {
7133 ASSERT(function->scope()->arguments()->IsStackAllocated());
7134 inner_env->Bind(function->scope()->arguments(),
7140 VisitStatements(function->body());
7141 if (HasStackOverflow()) {
7144 TraceInline(target, caller,
"inline graph construction failed");
7145 target_shared->DisableOptimization(
"inlining bailed out");
7146 inline_bailout_ =
true;
7147 delete target_state;
7152 inlined_count_ += nodes_added;
7154 ASSERT(unoptimized_code->kind() == Code::FUNCTION);
7155 Handle<Object> maybe_type_info(unoptimized_code->type_feedback_info());
7156 Handle<TypeFeedbackInfo> type_info(
7157 Handle<TypeFeedbackInfo>::cast(maybe_type_info));
7160 TraceInline(target, caller,
NULL);
7168 if (call_context()->
IsTest()) {
7170 }
else if (call_context()->IsEffect()) {
7173 ASSERT(call_context()->IsValue());
7180 if (call_context()->
IsTest()) {
7181 inlined_test_context()->
ReturnValue(implicit_return_value);
7182 }
else if (call_context()->IsEffect()) {
7185 ASSERT(call_context()->IsValue());
7191 if (call_context()->IsTest()) {
7193 }
else if (call_context()->IsEffect()) {
7196 ASSERT(call_context()->IsValue());
7203 if (inlined_test_context() !=
NULL) {
7204 HBasicBlock* if_true = inlined_test_context()->
if_true();
7205 HBasicBlock* if_false = inlined_test_context()->
if_false();
7208 ASSERT(ast_context() == inlined_test_context());
7209 ClearInlinedTestContext();
7210 delete target_state;
7213 if (if_true->HasPredecessor()) {
7214 if_true->SetJoinId(ast_id);
7218 if (if_false->HasPredecessor()) {
7219 if_false->SetJoinId(ast_id);
7226 }
else if (function_return()->HasPredecessor()) {
7232 delete target_state;
7237 bool HGraphBuilder::TryInlineCall(Call* expr,
bool drop_extra) {
7240 CallKind call_kind = (expr->expression()->AsProperty() ==
NULL)
7244 return TryInline(call_kind,
7246 expr->arguments()->length(),
7254 bool HGraphBuilder::TryInlineConstruct(CallNew* expr,
7255 HValue* implicit_return_value) {
7258 expr->arguments()->length(),
7259 implicit_return_value,
7266 bool HGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
7278 bool HGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
7279 Assignment* assignment,
7280 HValue* implicit_return_value) {
7284 implicit_return_value,
7286 assignment->AssignmentId(),
7291 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr,
bool drop_extra) {
7292 if (!expr->target()->shared()->HasBuiltinFunctionId())
return false;
7302 if (expr->arguments()->length() == 1) {
7303 HValue* argument =
Pop();
7306 HUnaryMathOperation* op =
7307 new(zone()) HUnaryMathOperation(context, argument,
id);
7308 op->set_position(expr->position());
7309 if (drop_extra) Drop(1);
7322 bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr,
7324 Handle<Map> receiver_map,
7328 if (!expr->target()->shared()->HasBuiltinFunctionId())
return false;
7330 int argument_count = expr->arguments()->length() + 1;
7332 case kStringCharCodeAt:
7334 if (argument_count == 2 && check_type ==
STRING_CHECK) {
7335 HValue* index =
Pop();
7336 HValue*
string =
Pop();
7338 ASSERT(!expr->holder().is_null());
7342 HStringCharCodeAt* char_code =
7343 BuildStringCharCodeAt(context,
string, index);
7344 if (
id == kStringCharCodeAt) {
7349 HStringCharFromCode* result =
7350 new(zone()) HStringCharFromCode(context, char_code);
7364 AddCheckConstantFunction(expr->holder(), receiver, receiver_map,
true);
7365 HValue* argument =
Pop();
7368 HUnaryMathOperation* op =
7369 new(zone()) HUnaryMathOperation(context, argument,
id);
7370 op->set_position(expr->position());
7377 AddCheckConstantFunction(expr->holder(), receiver, receiver_map,
true);
7378 HValue* right =
Pop();
7379 HValue* left =
Pop();
7382 HInstruction* result =
NULL;
7384 if (right->IsConstant() &&
HConstant::cast(right)->HasDoubleValue()) {
7386 if (exponent == 0.5) {
7388 new(zone()) HUnaryMathOperation(context, left,
kMathPowHalf);
7389 }
else if (exponent == -0.5) {
7390 HConstant* double_one =
7394 HUnaryMathOperation* square_root =
7395 new(zone()) HUnaryMathOperation(context, left,
kMathPowHalf);
7399 ASSERT(!square_root->HasObservableSideEffects());
7400 result =
new(zone()) HDiv(context, double_one, square_root);
7401 }
else if (exponent == 2.0) {
7402 result =
new(zone()) HMul(context, left, left);
7404 }
else if (right->IsConstant() &&
7407 result =
new(zone()) HMul(context, left, left);
7410 if (result ==
NULL) {
7411 result =
new(zone()) HPower(left, right);
7419 AddCheckConstantFunction(expr->holder(), receiver, receiver_map,
true);
7422 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
7424 HRandom* result =
new(zone()) HRandom(global_object);
7432 AddCheckConstantFunction(expr->holder(), receiver, receiver_map,
true);
7433 HValue* right =
Pop();
7434 HValue* left =
Pop();
7439 HMathMinMax* result =
new(zone()) HMathMinMax(context, left, right, op);
7452 bool HGraphBuilder::TryCallApply(Call* expr) {
7453 Expression* callee = expr->expression();
7454 Property* prop = callee->AsProperty();
7460 Handle<Map> function_map = expr->GetReceiverTypes()->first();
7462 !expr->target()->shared()->HasBuiltinFunctionId() ||
7463 expr->target()->shared()->builtin_function_id() != kFunctionApply) {
7469 ZoneList<Expression*>* args = expr->arguments();
7470 if (args->length() != 2)
return false;
7472 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
7473 if (arg_two ==
NULL || !arg_two->var()->IsStackAllocated())
return false;
7478 VisitForValue(prop->obj());
7480 HValue*
function = Top();
7481 AddCheckConstantFunction(expr->holder(),
function, function_map,
true);
7484 VisitForValue(args->at(0));
7486 HValue* receiver =
Pop();
7490 new(zone()) HArgumentsElements(
false));
7491 HInstruction* length =
7493 HValue* wrapped_receiver =
7495 HInstruction* result =
7496 new(zone()) HApplyArguments(
function,
7500 result->set_position(expr->position());
7508 HValue* wrapped_receiver =
7510 PushAndAdd(
new(zone()) HPushArgument(wrapped_receiver));
7515 for (
int i = 1; i < arguments_env->parameter_count(); i++) {
7516 PushAndAdd(
new(zone()) HPushArgument(arguments_env->Lookup(i)));
7519 HInvokeFunction* call =
new(zone()) HInvokeFunction(
7523 Drop(parameter_count);
7524 call->set_position(expr->position());
7531 void HGraphBuilder::VisitCall(Call* expr) {
7532 ASSERT(!HasStackOverflow());
7535 Expression* callee = expr->expression();
7536 int argument_count = expr->arguments()->length() + 1;
7537 HInstruction* call =
NULL;
7539 Property* prop = callee->AsProperty();
7541 if (!prop->key()->IsPropertyName()) {
7547 HValue* key =
Pop();
7548 HValue* receiver =
Pop();
7552 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7555 call =
new(zone()) HCallKeyed(context, key, argument_count);
7556 call->set_position(expr->position());
7557 Drop(argument_count + 1);
7564 if (TryCallApply(expr))
return;
7569 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
7571 SmallMapList* types = expr->GetReceiverTypes();
7575 if (expr->IsMonomorphic()) {
7576 Handle<Map> receiver_map = (types ==
NULL || types->is_empty())
7577 ? Handle<Map>::null()
7579 if (TryInlineBuiltinMethodCall(expr,
7582 expr->check_type())) {
7583 if (FLAG_trace_inlining) {
7584 PrintF(
"Inlining builtin ");
7585 expr->target()->ShortPrint();
7597 call = PreProcessCall(
7598 new(zone()) HCallNamed(context, name, argument_count));
7600 AddCheckConstantFunction(expr->holder(), receiver, receiver_map,
true);
7602 if (TryInlineCall(expr))
return;
7603 call = PreProcessCall(
7604 new(zone()) HCallConstantFunction(expr->target(),
7607 }
else if (types !=
NULL && types->length() > 1) {
7609 HandlePolymorphicCallNamed(expr, receiver, types, name);
7614 call = PreProcessCall(
7615 new(zone()) HCallNamed(context, name, argument_count));
7620 VariableProxy* proxy = expr->expression()->AsVariableProxy();
7621 bool global_call = proxy !=
NULL && proxy->var()->IsUnallocated();
7623 if (proxy !=
NULL && proxy->var()->is_possibly_eval()) {
7624 return Bailout(
"possible direct call to eval");
7628 Variable* var = proxy->var();
7629 bool known_global_function =
false;
7633 LookupResult lookup(isolate());
7634 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup,
false);
7635 if (type == kUseCell &&
7636 !info()->global_object()->IsAccessCheckNeeded()) {
7637 Handle<GlobalObject> global(info()->global_object());
7638 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
7640 if (known_global_function) {
7644 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
7645 PushAndAdd(global_object);
7649 HValue*
function =
Pop();
7650 AddInstruction(
new(zone()) HCheckFunction(
function, expr->target()));
7653 HGlobalReceiver* global_receiver =
7654 new(zone()) HGlobalReceiver(global_object);
7656 const int receiver_index = argument_count - 1;
7662 if (TryInlineBuiltinFunctionCall(expr,
false)) {
7663 if (FLAG_trace_inlining) {
7664 PrintF(
"Inlining builtin ");
7665 expr->target()->ShortPrint();
7670 if (TryInlineCall(expr))
return;
7672 if (expr->target().is_identical_to(info()->closure())) {
7676 call = PreProcessCall(
new(zone()) HCallKnownGlobal(expr->target(),
7680 HGlobalObject* receiver =
new(zone()) HGlobalObject(context);
7682 PushAndAdd(
new(zone()) HPushArgument(receiver));
7683 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7685 call =
new(zone()) HCallGlobal(context, var->name(), argument_count);
7686 Drop(argument_count);
7689 }
else if (expr->IsMonomorphic()) {
7693 HValue*
function = Top();
7695 HGlobalObject* global =
new(zone()) HGlobalObject(context);
7697 HGlobalReceiver* receiver =
new(zone()) HGlobalReceiver(global);
7698 PushAndAdd(receiver);
7700 AddInstruction(
new(zone()) HCheckFunction(
function, expr->target()));
7702 if (TryInlineBuiltinFunctionCall(expr,
true)) {
7703 if (FLAG_trace_inlining) {
7704 PrintF(
"Inlining builtin ");
7705 expr->target()->ShortPrint();
7711 if (TryInlineCall(expr,
true)) {
7714 call = PreProcessCall(
7715 new(zone()) HInvokeFunction(context,
7724 HValue*
function = Top();
7726 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
7728 HGlobalReceiver* receiver =
new(zone()) HGlobalReceiver(global_object);
7730 PushAndAdd(
new(zone()) HPushArgument(receiver));
7731 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7733 call =
new(zone()) HCallFunction(context,
function, argument_count);
7734 Drop(argument_count + 1);
7738 call->set_position(expr->position());
7744 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
7745 return constructor->has_initial_map() &&
7751 void HGraphBuilder::VisitCallNew(CallNew* expr) {
7752 ASSERT(!HasStackOverflow());
7755 expr->RecordTypeFeedback(
oracle());
7756 int argument_count = expr->arguments()->length() + 1;
7759 if (FLAG_inline_construct &&
7760 expr->IsMonomorphic() &&
7761 IsAllocationInlineable(expr->target())) {
7765 HValue*
function = Top();
7767 Handle<JSFunction> constructor = expr->target();
7769 new(zone()) HCheckFunction(
function, constructor));
7773 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) {
7774 constructor->shared()->CompleteInobjectSlackTracking();
7778 HInstruction* receiver =
new(zone()) HAllocateObject(context, constructor);
7780 const int receiver_index = argument_count - 1;
7785 if (TryInlineConstruct(expr, receiver))
return;
7791 receiver->DeleteAndReplaceWith(
NULL);
7792 check->DeleteAndReplaceWith(
NULL);
7794 HInstruction* call = PreProcessCall(
7795 new(zone()) HCallNew(context,
function, argument_count));
7796 call->set_position(expr->position());
7803 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7804 HInstruction* call =
7805 new(zone()) HCallNew(context, constructor, argument_count);
7806 Drop(argument_count);
7807 call->set_position(expr->position());
7817 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
7818 &HGraphBuilder::Generate##Name,
7820 const HGraphBuilder::InlineFunctionGenerator
7821 HGraphBuilder::kInlineFunctionGenerators[] = {
7825 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
7828 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
7829 ASSERT(!HasStackOverflow());
7832 if (expr->is_jsruntime()) {
7833 return Bailout(
"call to a JavaScript runtime function");
7836 const Runtime::Function*
function = expr->function();
7839 ASSERT(expr->name()->length() > 0);
7840 ASSERT(expr->name()->Get(0) ==
'_');
7842 int lookup_index =
static_cast<int>(
function->function_id) -
7844 ASSERT(lookup_index >= 0);
7845 ASSERT(static_cast<size_t>(lookup_index) <
7847 InlineFunctionGenerator
generator = kInlineFunctionGenerators[lookup_index];
7853 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7856 Handle<String> name = expr->name();
7857 int argument_count = expr->arguments()->length();
7858 HCallRuntime* call =
7859 new(zone()) HCallRuntime(context, name,
function, argument_count);
7860 Drop(argument_count);
7866 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
7867 ASSERT(!HasStackOverflow());
7870 switch (expr->op()) {
7871 case Token::DELETE:
return VisitDelete(expr);
7873 case Token::TYPEOF:
return VisitTypeof(expr);
7876 case Token::BIT_NOT:
return VisitBitNot(expr);
7877 case Token::NOT:
return VisitNot(expr);
7882 void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
7883 Property* prop = expr->expression()->AsProperty();
7884 VariableProxy* proxy = expr->expression()->AsVariableProxy();
7888 HValue* key =
Pop();
7889 HValue* obj =
Pop();
7891 HDeleteProperty* instr =
new(zone()) HDeleteProperty(context, obj, key);
7893 }
else if (proxy !=
NULL) {
7894 Variable* var = proxy->var();
7895 if (var->IsUnallocated()) {
7896 Bailout(
"delete with global variable");
7897 }
else if (var->IsStackAllocated() || var->IsContextSlot()) {
7901 HValue* value = var->is_this()
7906 Bailout(
"delete with non-global variable");
7917 void HGraphBuilder::VisitVoid(UnaryOperation* expr) {
7923 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) {
7925 HValue* value =
Pop();
7927 HInstruction* instr =
new(zone()) HTypeof(context, value);
7932 void HGraphBuilder::VisitAdd(UnaryOperation* expr) {
7934 HValue* value =
Pop();
7936 HInstruction* instr =
7937 new(zone()) HMul(context, value, graph_->
GetConstant1());
7942 void HGraphBuilder::VisitSub(UnaryOperation* expr) {
7944 HValue* value =
Pop();
7946 HInstruction* instr =
7949 if (info.IsUninitialized()) {
7954 Representation rep = ToRepresentation(info);
7955 TraceRepresentation(expr->op(), info, instr, rep);
7956 instr->AssumeRepresentation(rep);
7961 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
7963 HValue* value =
Pop();
7965 if (info.IsUninitialized()) {
7969 HInstruction* instr =
new(zone()) HBitNot(value);
7974 void HGraphBuilder::VisitNot(UnaryOperation* expr) {
7975 if (ast_context()->IsTest()) {
7977 VisitForControl(expr->expression(),
7978 context->if_false(),
7979 context->if_true());
7984 VisitForEffect(expr->expression());
7988 ASSERT(ast_context()->IsValue());
7995 if (materialize_false->HasPredecessor()) {
7996 materialize_false->SetJoinId(expr->MaterializeFalseId());
8000 materialize_false =
NULL;
8003 if (materialize_true->HasPredecessor()) {
8004 materialize_true->SetJoinId(expr->MaterializeTrueId());
8008 materialize_true =
NULL;
8012 CreateJoin(materialize_false, materialize_true, expr->id());
8018 HInstruction* HGraphBuilder::BuildIncrement(
bool returns_original_input,
8019 CountOperation* expr) {
8022 Representation rep = ToRepresentation(info);
8023 if (rep.IsTagged()) {
8027 if (returns_original_input) {
8032 HInstruction* number_input =
new(zone()) HForceRepresentation(
Pop(), rep);
8040 HConstant* delta = (expr->op() == Token::INC)
8044 HInstruction* instr =
new(zone()) HAdd(context, Top(), delta);
8045 TraceRepresentation(expr->op(), info, instr, rep);
8046 instr->AssumeRepresentation(rep);
8052 void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
8053 ASSERT(!HasStackOverflow());
8056 Expression* target = expr->expression();
8057 VariableProxy* proxy = target->AsVariableProxy();
8058 Property* prop = target->AsProperty();
8059 if (proxy ==
NULL && prop ==
NULL) {
8060 return Bailout(
"invalid lhs in count operation");
8066 bool returns_original_input =
8067 expr->is_postfix() && !ast_context()->
IsEffect();
8068 HValue* input =
NULL;
8069 HValue* after =
NULL;
8071 if (proxy !=
NULL) {
8072 Variable* var = proxy->var();
8073 if (var->mode() ==
CONST) {
8074 return Bailout(
"unsupported count operation with const");
8080 after = BuildIncrement(returns_original_input, expr);
8081 input = returns_original_input ? Top() :
Pop();
8084 switch (var->location()) {
8086 HandleGlobalVariableAssignment(var,
8089 expr->AssignmentId());
8101 if (info()->scope()->arguments() !=
NULL) {
8105 int count = info()->scope()->num_parameters();
8106 for (
int i = 0; i < count; ++i) {
8107 if (var == info()->scope()->parameter(i)) {
8108 return Bailout(
"assignment to parameter in arguments object");
8113 HValue* context = BuildContextChainWalk(var);
8116 HStoreContextSlot* instr =
8117 new(zone()) HStoreContextSlot(context, var->index(), mode, after);
8119 if (instr->HasObservableSideEffects()) {
8126 return Bailout(
"lookup variable in count operation");
8132 prop->RecordTypeFeedback(
oracle(), zone());
8134 if (prop->key()->IsPropertyName()) {
8139 HValue*
object = Top();
8141 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
8144 bool monomorphic = prop->IsMonomorphic();
8146 map = prop->GetReceiverTypes()->first();
8147 if (map->is_dictionary_map()) monomorphic =
false;
8150 Handle<JSFunction> getter;
8151 Handle<JSObject> holder;
8152 if (LookupGetter(map, name, &getter, &holder)) {
8153 load = BuildCallGetter(
object, map, getter, holder);
8155 load = BuildLoadNamedMonomorphic(
object, name, prop, map);
8158 load = BuildLoadNamedGeneric(
object, name, prop);
8161 if (load->HasObservableSideEffects())
AddSimulate(prop->LoadId());
8163 after = BuildIncrement(returns_original_input, expr);
8166 HInstruction* store;
8169 CHECK_ALIVE(store = BuildStoreNamedGeneric(
object, name, after));
8171 Handle<JSFunction> setter;
8172 Handle<JSObject> holder;
8173 if (LookupSetter(map, name, &setter, &holder)) {
8174 store = BuildCallSetter(
object, after, map, setter, holder);
8176 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(
object,
8189 if (store->HasObservableSideEffects())
AddSimulate(expr->AssignmentId());
8200 bool has_side_effects =
false;
8201 HValue* load = HandleKeyedElementAccess(
8202 obj, key,
NULL, prop, prop->LoadId(), RelocInfo::kNoPosition,
8206 if (has_side_effects)
AddSimulate(prop->LoadId());
8208 after = BuildIncrement(returns_original_input, expr);
8211 expr->RecordTypeFeedback(
oracle(), zone());
8212 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(),
8213 RelocInfo::kNoPosition,
8223 ASSERT(has_side_effects);
8228 Drop(returns_original_input ? 2 : 1);
8229 return ast_context()->
ReturnValue(expr->is_postfix() ? input : after);
8233 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context,
8238 HStringLength* length =
new(zone()) HStringLength(
string);
8240 HInstruction* checked_index =
8242 return new(zone()) HStringCharCodeAt(context,
string, checked_index);
8246 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
8251 if (info.IsUninitialized()) {
8256 HInstruction* instr =
NULL;
8257 switch (expr->op()) {
8259 if (info.IsString()) {
8264 instr =
new(zone()) HStringAdd(context, left, right);
8281 case Token::BIT_XOR:
8282 case Token::BIT_AND:
8291 if (FLAG_opt_safe_uint32_operations && instr->IsShr()) {
8292 bool can_be_shift_by_zero =
true;
8293 if (right->IsConstant()) {
8295 if (right_const->HasInteger32Value() &&
8296 (right_const->Integer32Value() & 0x1f) != 0) {
8297 can_be_shift_by_zero =
false;
8315 ((left->IsConstant() &&
HConstant::cast(left)->handle()->IsString()) ||
8316 (right->IsConstant() &&
HConstant::cast(right)->handle()->IsString()))) {
8319 Representation rep = ToRepresentation(info);
8321 if (instr->IsBitwiseBinaryOperation()) {
8323 InitializeObservedInputRepresentation(rep);
8326 TraceRepresentation(expr->op(), info, instr, rep);
8327 instr->AssumeRepresentation(rep);
8333 static bool IsClassOfTest(CompareOperation* expr) {
8334 if (expr->op() != Token::EQ_STRICT)
return false;
8335 CallRuntime* call = expr->left()->AsCallRuntime();
8336 if (call ==
NULL)
return false;
8337 Literal* literal = expr->right()->AsLiteral();
8338 if (literal ==
NULL)
return false;
8339 if (!literal->handle()->IsString())
return false;
8340 if (!call->name()->IsEqualTo(
CStrVector(
"_ClassOf")))
return false;
8341 ASSERT(call->arguments()->length() == 1);
8346 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
8347 ASSERT(!HasStackOverflow());
8350 switch (expr->op()) {
8352 return VisitComma(expr);
8355 return VisitLogicalExpression(expr);
8357 return VisitArithmeticExpression(expr);
8362 void HGraphBuilder::VisitComma(BinaryOperation* expr) {
8366 Visit(expr->right());
8370 void HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
8371 bool is_logical_and = expr->op() ==
Token::AND;
8372 if (ast_context()->IsTest()) {
8376 if (is_logical_and) {
8379 context->if_false()));
8388 if (eval_right->HasPredecessor()) {
8389 eval_right->SetJoinId(expr->RightId());
8391 Visit(expr->right());
8394 }
else if (ast_context()->
IsValue()) {
8401 TypeFeedbackId test_id = expr->left()->test_id();
8402 ToBooleanStub::Types expected(
oracle()->ToBooleanTypes(test_id));
8403 HBranch* test = is_logical_and
8404 ?
new(zone()) HBranch(Top(), eval_right, empty_block, expected)
8405 :
new(zone()) HBranch(Top(), empty_block, eval_right, expected);
8412 HBasicBlock* join_block =
8418 ASSERT(ast_context()->IsEffect());
8424 if (is_logical_and) {
8425 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
8427 CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
8436 if (empty_block->HasPredecessor()) {
8437 empty_block->SetJoinId(expr->id());
8442 if (right_block->HasPredecessor()) {
8443 right_block->SetJoinId(expr->RightId());
8451 HBasicBlock* join_block =
8452 CreateJoin(empty_block, right_block, expr->id());
8460 void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
8463 HValue* right =
Pop();
8464 HValue* left =
Pop();
8465 HInstruction* instr = BuildBinaryOperation(expr, left, right);
8466 instr->set_position(expr->position());
8471 void HGraphBuilder::TraceRepresentation(
Token::Value op,
8474 Representation rep) {
8475 if (!FLAG_trace_representation)
return;
8479 PrintF(
"Operation %s has type info %s, %schange representation assumption "
8480 "for %s (ID %d) from %s to %s\n",
8483 flexible ?
"" :
" DO NOT ",
8486 value->representation().Mnemonic(),
8491 Representation HGraphBuilder::ToRepresentation(TypeInfo info) {
8500 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
8501 HTypeof* typeof_expr,
8502 Handle<String> check) {
8504 HValue* value = typeof_expr->value();
8505 HTypeofIsAndBranch* instr =
new(zone()) HTypeofIsAndBranch(value, check);
8506 instr->set_position(expr->position());
8511 static bool MatchLiteralCompareNil(HValue* left,
8516 if (left->IsConstant() &&
8526 static bool MatchLiteralCompareTypeof(HValue* left,
8529 HTypeof** typeof_expr,
8530 Handle<String>* check) {
8531 if (left->IsTypeof() &&
8533 right->IsConstant() &&
8543 static bool IsLiteralCompareTypeof(HValue* left,
8546 HTypeof** typeof_expr,
8547 Handle<String>* check) {
8548 return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) ||
8549 MatchLiteralCompareTypeof(right, op, left, typeof_expr, check);
8553 static bool IsLiteralCompareNil(HValue* left,
8558 return MatchLiteralCompareNil(left, op, right, nil, expr) ||
8559 MatchLiteralCompareNil(right, op, left, nil, expr);
8563 static bool IsLiteralCompareBool(HValue* left,
8566 return op == Token::EQ_STRICT &&
8567 ((left->IsConstant() &&
HConstant::cast(left)->handle()->IsBoolean()) ||
8568 (right->IsConstant() &&
HConstant::cast(right)->handle()->IsBoolean()));
8572 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
8573 ASSERT(!HasStackOverflow());
8576 if (IsClassOfTest(expr)) {
8577 CallRuntime* call = expr->left()->AsCallRuntime();
8578 ASSERT(call->arguments()->length() == 1);
8579 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8580 HValue* value =
Pop();
8581 Literal* literal = expr->right()->AsLiteral();
8583 HClassOfTestAndBranch* instr =
8584 new(zone()) HClassOfTestAndBranch(value, rhs);
8585 instr->set_position(expr->position());
8592 if (type_info.IsUninitialized()) {
8602 HValue* right =
Pop();
8603 HValue* left =
Pop();
8606 HTypeof* typeof_expr =
NULL;
8607 Handle<String>
check;
8608 if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) {
8609 return HandleLiteralCompareTypeof(expr, typeof_expr, check);
8611 HValue* sub_expr =
NULL;
8613 if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) {
8616 if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) {
8617 return HandleLiteralCompareNil(expr, sub_expr,
kNullValue);
8619 if (IsLiteralCompareBool(left, op, right)) {
8620 HCompareObjectEqAndBranch* result =
8621 new(zone()) HCompareObjectEqAndBranch(left, right);
8622 result->set_position(expr->position());
8626 if (op == Token::INSTANCEOF) {
8631 VariableProxy* proxy = expr->right()->AsVariableProxy();
8632 bool global_function = (proxy !=
NULL) && proxy->var()->IsUnallocated();
8633 if (global_function &&
8634 info()->has_global_object() &&
8635 !info()->global_object()->IsAccessCheckNeeded()) {
8636 Handle<String> name = proxy->name();
8637 Handle<GlobalObject> global(info()->global_object());
8638 LookupResult lookup(isolate());
8639 global->Lookup(*name, &lookup);
8640 if (lookup.IsNormal() && lookup.GetValue()->IsJSFunction()) {
8644 if (!isolate()->heap()->InNewSpace(*candidate)) {
8652 if (target.is_null()) {
8653 HInstanceOf* result =
new(zone()) HInstanceOf(context, left, right);
8654 result->set_position(expr->position());
8658 HInstanceOfKnownGlobal* result =
8659 new(zone()) HInstanceOfKnownGlobal(context, left, target);
8660 result->set_position(expr->position());
8664 HIn* result =
new(zone()) HIn(context, left, right);
8665 result->set_position(expr->position());
8667 }
else if (type_info.IsNonPrimitive()) {
8670 case Token::EQ_STRICT: {
8673 if (!map.is_null()) {
8678 HCompareObjectEqAndBranch* result =
8679 new(zone()) HCompareObjectEqAndBranch(left, right);
8680 result->set_position(expr->position());
8687 HCompareObjectEqAndBranch* result =
8688 new(zone()) HCompareObjectEqAndBranch(left, right);
8689 result->set_position(expr->position());
8694 return Bailout(
"Unsupported non-primitive compare");
8697 (op ==
Token::EQ || op == Token::EQ_STRICT)) {
8702 HCompareObjectEqAndBranch* result =
8703 new(zone()) HCompareObjectEqAndBranch(left, right);
8704 result->set_position(expr->position());
8707 Representation r = ToRepresentation(type_info);
8709 HCompareGeneric* result =
8710 new(zone()) HCompareGeneric(context, left, right, op);
8711 result->set_position(expr->position());
8714 HCompareIDAndBranch* result =
8715 new(zone()) HCompareIDAndBranch(left, right, op);
8716 result->set_position(expr->position());
8717 result->SetInputRepresentation(r);
8724 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
8727 ASSERT(!HasStackOverflow());
8732 HIsNilAndBranch* instr =
new(zone()) HIsNilAndBranch(value, kind, nil);
8733 instr->set_position(expr->position());
8738 HInstruction* HGraphBuilder::BuildThisFunction() {
8742 return new(zone()) HConstant(
8746 return new(zone()) HThisFunction;
8751 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
8752 ASSERT(!HasStackOverflow());
8755 HInstruction* instr = BuildThisFunction();
8761 ASSERT(globals_.is_empty());
8762 AstVisitor::VisitDeclarations(declarations);
8763 if (!globals_.is_empty()) {
8765 isolate()->factory()->NewFixedArray(globals_.length(),
TENURED);
8766 for (
int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.
at(i));
8785 globals_.
Add(variable->
name(), zone());
8787 ? isolate()->factory()->the_hole_value()
8788 : isolate()->factory()->undefined_value(), zone());
8801 HStoreContextSlot* store =
new(zone()) HStoreContextSlot(
8804 if (store->HasObservableSideEffects())
AddSimulate(proxy->
id());
8808 return Bailout(
"unsupported lookup slot in declaration");
8813 void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* declaration) {
8814 VariableProxy* proxy = declaration->proxy();
8815 Variable* variable = proxy->var();
8816 switch (variable->location()) {
8818 globals_.
Add(variable->name(), zone());
8819 Handle<SharedFunctionInfo>
function =
8822 if (
function.is_null())
return SetStackOverflow();
8823 globals_.
Add(
function, zone());
8829 HValue* value =
Pop();
8835 HValue* value =
Pop();
8837 HStoreContextSlot* store =
new(zone()) HStoreContextSlot(
8840 if (store->HasObservableSideEffects())
AddSimulate(proxy->id());
8844 return Bailout(
"unsupported lookup slot in declaration");
8849 void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* declaration) {
8854 void HGraphBuilder::VisitImportDeclaration(ImportDeclaration* declaration) {
8859 void HGraphBuilder::VisitExportDeclaration(ExportDeclaration* declaration) {
8864 void HGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) {
8869 void HGraphBuilder::VisitModuleVariable(ModuleVariable* module) {
8874 void HGraphBuilder::VisitModulePath(ModulePath* module) {
8879 void HGraphBuilder::VisitModuleUrl(ModuleUrl* module) {
8886 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
8887 ASSERT(call->arguments()->length() == 1);
8888 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8889 HValue* value =
Pop();
8890 HIsSmiAndBranch* result =
new(zone()) HIsSmiAndBranch(value);
8895 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
8896 ASSERT(call->arguments()->length() == 1);
8897 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8898 HValue* value =
Pop();
8899 HHasInstanceTypeAndBranch* result =
8900 new(zone()) HHasInstanceTypeAndBranch(value,
8907 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
8908 ASSERT(call->arguments()->length() == 1);
8909 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8910 HValue* value =
Pop();
8911 HHasInstanceTypeAndBranch* result =
8917 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
8918 ASSERT(call->arguments()->length() == 1);
8919 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8920 HValue* value =
Pop();
8921 HHasCachedArrayIndexAndBranch* result =
8922 new(zone()) HHasCachedArrayIndexAndBranch(value);
8927 void HGraphBuilder::GenerateIsArray(CallRuntime* call) {
8928 ASSERT(call->arguments()->length() == 1);
8929 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8930 HValue* value =
Pop();
8931 HHasInstanceTypeAndBranch* result =
8932 new(zone()) HHasInstanceTypeAndBranch(value,
JS_ARRAY_TYPE);
8937 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
8938 ASSERT(call->arguments()->length() == 1);
8939 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8940 HValue* value =
Pop();
8941 HHasInstanceTypeAndBranch* result =
8947 void HGraphBuilder::GenerateIsObject(CallRuntime* call) {
8948 ASSERT(call->arguments()->length() == 1);
8949 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8950 HValue* value =
Pop();
8951 HIsObjectAndBranch* result =
new(zone()) HIsObjectAndBranch(value);
8956 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
8957 return Bailout(
"inlined runtime function: IsNonNegativeSmi");
8961 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
8962 ASSERT(call->arguments()->length() == 1);
8963 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8964 HValue* value =
Pop();
8965 HIsUndetectableAndBranch* result =
8966 new(zone()) HIsUndetectableAndBranch(value);
8971 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
8972 CallRuntime* call) {
8974 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
8979 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
8980 ASSERT(call->arguments()->length() == 0);
8988 return ast_context()->
ReturnControl(
new(zone()) HIsConstructCallAndBranch,
8995 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
9000 ASSERT(call->arguments()->length() == 0);
9002 new(zone()) HArgumentsElements(
false));
9003 HArgumentsLength* result =
new(zone()) HArgumentsLength(elements);
9008 void HGraphBuilder::GenerateArguments(CallRuntime* call) {
9013 ASSERT(call->arguments()->length() == 1);
9014 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9015 HValue* index =
Pop();
9017 new(zone()) HArgumentsElements(
false));
9018 HInstruction* length =
AddInstruction(
new(zone()) HArgumentsLength(elements));
9019 HInstruction* checked_index =
9021 HAccessArgumentsAt* result =
9022 new(zone()) HAccessArgumentsAt(elements, length, checked_index);
9028 void HGraphBuilder::GenerateClassOf(CallRuntime* call) {
9031 return Bailout(
"inlined runtime function: ClassOf");
9035 void HGraphBuilder::GenerateValueOf(CallRuntime* call) {
9036 ASSERT(call->arguments()->length() == 1);
9037 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9038 HValue* value =
Pop();
9039 HValueOf* result =
new(zone()) HValueOf(value);
9044 void HGraphBuilder::GenerateDateField(CallRuntime* call) {
9045 ASSERT(call->arguments()->length() == 2);
9047 Smi* index =
Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle()));
9048 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9049 HValue* date =
Pop();
9050 HDateField* result =
new(zone()) HDateField(date, index);
9055 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
9056 ASSERT(call->arguments()->length() == 2);
9057 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9058 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9059 HValue* value =
Pop();
9060 HValue*
object =
Pop();
9062 HIsSmiAndBranch* smicheck =
new(zone()) HIsSmiAndBranch(
object);
9066 smicheck->SetSuccessorAt(0, if_smi);
9067 smicheck->SetSuccessorAt(1, if_heap_object);
9073 HHasInstanceTypeAndBranch* typecheck =
9074 new(zone()) HHasInstanceTypeAndBranch(
object,
JS_VALUE_TYPE);
9077 typecheck->SetSuccessorAt(0, if_js_value);
9078 typecheck->SetSuccessorAt(1, not_js_value);
9080 not_js_value->Goto(join);
9084 Handle<String> name = isolate()->factory()->undefined_symbol();
9090 if_js_value->Goto(join);
9091 join->SetJoinId(call->id());
9098 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
9099 ASSERT(call->arguments()->length() == 2);
9100 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9101 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9102 HValue* index =
Pop();
9103 HValue*
string =
Pop();
9105 HStringCharCodeAt* result = BuildStringCharCodeAt(context,
string, index);
9111 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
9112 ASSERT(call->arguments()->length() == 1);
9113 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9114 HValue* char_code =
Pop();
9116 HStringCharFromCode* result =
9117 new(zone()) HStringCharFromCode(context, char_code);
9123 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
9124 ASSERT(call->arguments()->length() == 2);
9125 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9126 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9127 HValue* index =
Pop();
9128 HValue*
string =
Pop();
9130 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context,
string, index);
9132 HStringCharFromCode* result =
9133 new(zone()) HStringCharFromCode(context, char_code);
9139 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
9140 ASSERT(call->arguments()->length() == 2);
9141 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9142 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9143 HValue* right =
Pop();
9144 HValue* left =
Pop();
9145 HCompareObjectEqAndBranch* result =
9146 new(zone()) HCompareObjectEqAndBranch(left, right);
9151 void HGraphBuilder::GenerateLog(CallRuntime* call) {
9158 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
9160 HGlobalObject* global_object =
new(zone()) HGlobalObject(context);
9162 HRandom* result =
new(zone()) HRandom(global_object);
9168 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) {
9169 ASSERT_EQ(2, call->arguments()->length());
9170 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9172 HCallStub* result =
new(zone()) HCallStub(context, CodeStub::StringAdd, 2);
9179 void HGraphBuilder::GenerateSubString(CallRuntime* call) {
9180 ASSERT_EQ(3, call->arguments()->length());
9181 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9190 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) {
9191 ASSERT_EQ(2, call->arguments()->length());
9192 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9195 new(zone()) HCallStub(context, CodeStub::StringCompare, 2);
9202 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
9203 ASSERT_EQ(4, call->arguments()->length());
9204 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9206 HCallStub* result =
new(zone()) HCallStub(context, CodeStub::RegExpExec, 4);
9213 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
9214 ASSERT_EQ(3, call->arguments()->length());
9215 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9218 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3);
9225 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
9226 return Bailout(
"inlined runtime function: GetFromCache");
9231 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) {
9232 ASSERT_EQ(1, call->arguments()->length());
9233 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9236 new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
9243 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
9245 int arg_count = call->arguments()->length() - 1;
9248 for (
int i = 0; i < arg_count; ++i) {
9249 CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
9251 CHECK_ALIVE(VisitForValue(call->arguments()->last()));
9253 HValue*
function =
Pop();
9257 HHasInstanceTypeAndBranch* typecheck =
9262 typecheck->SetSuccessorAt(0, if_jsfunction);
9263 typecheck->SetSuccessorAt(1, if_nonfunction);
9268 new(zone()) HInvokeFunction(context,
function, arg_count));
9270 Push(invoke_result);
9271 if_jsfunction->Goto(join);
9275 new(zone()) HCallFunction(context,
function, arg_count));
9278 if_nonfunction->Goto(join);
9281 join->SetJoinId(call->id());
9287 void HGraphBuilder::GenerateMathPow(CallRuntime* call) {
9288 ASSERT_EQ(2, call->arguments()->length());
9289 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9290 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9291 HValue* right =
Pop();
9292 HValue* left =
Pop();
9293 HPower* result =
new(zone()) HPower(left, right);
9298 void HGraphBuilder::GenerateMathSin(CallRuntime* call) {
9299 ASSERT_EQ(1, call->arguments()->length());
9300 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9303 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
9310 void HGraphBuilder::GenerateMathCos(CallRuntime* call) {
9311 ASSERT_EQ(1, call->arguments()->length());
9312 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9315 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
9322 void HGraphBuilder::GenerateMathTan(CallRuntime* call) {
9323 ASSERT_EQ(1, call->arguments()->length());
9324 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9327 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
9334 void HGraphBuilder::GenerateMathLog(CallRuntime* call) {
9335 ASSERT_EQ(1, call->arguments()->length());
9336 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9339 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
9346 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
9347 return Bailout(
"inlined runtime function: MathSqrt");
9352 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
9353 return Bailout(
"inlined runtime function: IsRegExpEquivalent");
9357 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
9358 ASSERT(call->arguments()->length() == 1);
9359 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9360 HValue* value =
Pop();
9361 HGetCachedArrayIndex* result =
new(zone()) HGetCachedArrayIndex(value);
9366 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
9367 return Bailout(
"inlined runtime function: FastAsciiArrayJoin");
9371 #undef CHECK_BAILOUT
9379 : closure_(closure),
9381 assigned_variables_(4, zone),
9383 parameter_count_(0),
9398 assigned_variables_(0, zone),
9400 parameter_count_(0),
9407 ast_id_(other->ast_id()),
9418 : closure_(closure),
9419 values_(arguments, zone),
9420 assigned_variables_(0, zone),
9421 frame_type_(frame_type),
9422 parameter_count_(arguments),
9428 ast_id_(BailoutId::
None()),
9433 void HEnvironment::Initialize(
int parameter_count,
9440 int total = parameter_count + specials_count_ + local_count + stack_height;
9441 values_.Initialize(total + 4,
zone());
9442 for (
int i = 0; i < total; ++i) values_.Add(
NULL, zone());
9446 void HEnvironment::Initialize(
const HEnvironment* other) {
9447 closure_ = other->closure();
9448 values_.AddAll(other->values_, zone());
9449 assigned_variables_.
AddAll(other->assigned_variables_, zone());
9450 frame_type_ = other->frame_type_;
9451 parameter_count_ = other->parameter_count_;
9452 local_count_ = other->local_count_;
9453 if (other->outer_ !=
NULL) outer_ = other->outer_->
Copy();
9454 entry_ = other->entry_;
9455 pop_count_ = other->pop_count_;
9456 push_count_ = other->push_count_;
9457 ast_id_ = other->ast_id_;
9463 ASSERT(values_.length() == other->values_.length());
9465 int length = values_.length();
9466 for (
int i = 0; i <
length; ++i) {
9467 HValue* value = values_[i];
9468 if (value !=
NULL && value->
IsPhi() && value->
block() == block) {
9475 }
else if (values_[i] != other->values_[i]) {
9479 HValue* old_value = values_[i];
9480 for (
int j = 0; j < block->
predecessors()->length(); j++) {
9484 this->values_[i] = phi;
9493 if (!assigned_variables_.
Contains(index)) {
9494 assigned_variables_.
Add(index,
zone());
9496 values_[index] = value;
9500 bool HEnvironment::HasExpressionAt(
int index)
const {
9501 return index >= parameter_count_ + specials_count_ + local_count_;
9512 int count = index_from_top + 1;
9513 int index = values_.length() - count;
9514 ASSERT(HasExpressionAt(index));
9517 if (push_count_ < count) {
9519 pop_count_ += (count - push_count_);
9520 push_count_ = count;
9522 values_[index] = value;
9527 for (
int i = 0; i < count; ++i) {
9547 for (
int i = 0; i < values_.length(); ++i) {
9550 new_env->values_[i] = phi;
9551 loop_header->
AddPhi(phi);
9561 int arguments)
const {
9564 arguments + 1,
zone());
9565 for (
int i = 0; i <= arguments; ++i) {
9583 int arity =
function->scope()->num_parameters();
9586 outer->
Drop(arguments + 1);
9593 outer = CreateStubEnvironment(outer, target,
JS_CONSTRUCT, arguments);
9597 outer = CreateStubEnvironment(outer, target,
JS_GETTER, arguments);
9601 outer = CreateStubEnvironment(outer, target,
JS_SETTER, arguments);
9604 if (arity != arguments) {
9612 for (
int i = 0; i <= arity; ++i) {
9613 HValue* push = (i <= arguments) ?
9620 if ((target->shared()->native() || !
function->is_classic_mode()) &&
9625 for (
int i = arity + 2; i < inner->
length(); ++i) {
9635 for (
int i = 0; i <
length(); i++) {
9636 if (i == 0) stream->
Add(
"parameters\n");
9640 stream->
Add(
"expressions\n");
9642 HValue* val = values_.at(i);
9643 stream->
Add(
"%d: ", i);
9647 stream->
Add(
"NULL");
9664 Tag tag(
this,
"compilation");
9666 PrintStringProperty(
"name", *name->ToCString());
9667 PrintStringProperty(
"method", *name->ToCString());
9682 void HTracer::Trace(
const char* name,
HGraph* graph,
LChunk* chunk) {
9683 Tag tag(
this,
"cfg");
9684 PrintStringProperty(
"name", name);
9686 for (
int i = 0; i < blocks->length(); i++) {
9688 Tag block_tag(
this,
"block");
9689 PrintBlockProperty(
"name", current->
block_id());
9690 PrintIntProperty(
"from_bci", -1);
9691 PrintIntProperty(
"to_bci", -1);
9695 trace_.
Add(
"predecessors");
9696 for (
int j = 0; j < current->
predecessors()->length(); ++j) {
9701 PrintEmptyProperty(
"predecessors");
9705 PrintEmptyProperty(
"successors");
9708 trace_.
Add(
"successors");
9709 for (HSuccessorIterator it(current->
end()); !it.Done(); it.Advance()) {
9710 trace_.
Add(
" \"B%d\"", it.Current()->block_id());
9715 PrintEmptyProperty(
"xhandlers");
9719 PrintStringProperty(
"flags", flags);
9727 if (chunk !=
NULL) {
9739 Tag states_tag(
this,
"states");
9740 Tag locals_tag(
this,
"locals");
9741 int total = current->
phis()->length();
9742 PrintIntProperty(
"size", current->
phis()->length());
9743 PrintStringProperty(
"method",
"None");
9744 for (
int j = 0; j < total; ++j) {
9745 HPhi* phi = current->
phis()->at(j);
9747 trace_.
Add(
"%d ", phi->merged_index());
9748 phi->PrintNameTo(&trace_);
9750 phi->PrintTo(&trace_);
9756 Tag HIR_tag(
this,
"HIR");
9757 HInstruction* instruction = current->
first();
9758 while (instruction !=
NULL) {
9760 int uses = instruction->
UseCount();
9762 trace_.
Add(
"%d %d ", bci, uses);
9763 instruction->PrintNameTo(&trace_);
9765 instruction->PrintTo(&trace_);
9766 trace_.
Add(
" <|@\n");
9767 instruction = instruction->next();
9772 if (chunk !=
NULL) {
9773 Tag LIR_tag(
this,
"LIR");
9776 if (first_index != -1 && last_index != -1) {
9778 for (
int i = first_index; i <= last_index; ++i) {
9779 LInstruction* linstr = instructions->at(i);
9780 if (linstr !=
NULL) {
9784 linstr->PrintTo(&trace_);
9785 trace_.
Add(
" <|@\n");
9795 Tag tag(
this,
"intervals");
9796 PrintStringProperty(
"name", name);
9799 for (
int i = 0; i < fixed_d->
length(); ++i) {
9800 TraceLiveRange(fixed_d->
at(i),
"fixed", allocator->zone());
9804 for (
int i = 0; i < fixed->
length(); ++i) {
9805 TraceLiveRange(fixed->
at(i),
"fixed", allocator->zone());
9809 for (
int i = 0; i < live_ranges->length(); ++i) {
9810 TraceLiveRange(live_ranges->
at(i),
"object", allocator->zone());
9815 void HTracer::TraceLiveRange(
LiveRange* range,
const char* type,
9819 trace_.
Add(
"%d %s", range->
id(), type);
9822 int assigned_reg = op->
index();
9823 if (op->IsDoubleRegister()) {
9824 trace_.
Add(
" \"%s\"",
9827 ASSERT(op->IsRegister());
9832 if (op->IsDoubleStackSlot()) {
9833 trace_.
Add(
" \"double_stack:%d\"", op->index());
9835 ASSERT(op->IsStackSlot());
9836 trace_.
Add(
" \"stack:%d\"", op->index());
9839 int parent_index = -1;
9841 parent_index = range->
parent()->
id();
9843 parent_index = range->
id();
9846 int hint_index = -1;
9847 if (op !=
NULL && op->IsUnallocated()) {
9850 trace_.
Add(
" %d %d", parent_index, hint_index);
9852 while (cur_interval !=
NULL && range->
Covers(cur_interval->start())) {
9853 trace_.
Add(
" [%d, %d[",
9854 cur_interval->start().Value(),
9855 cur_interval->end().Value());
9856 cur_interval = cur_interval->next();
9859 UsePosition* current_pos = range->
first_pos();
9860 while (current_pos !=
NULL) {
9861 if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
9862 trace_.
Add(
" %d M", current_pos->pos().Value());
9864 current_pos = current_pos->next();
9867 trace_.
Add(
" \"\"\n");
9872 void HTracer::FlushToFile() {
9879 source_size_ += info->
shared_info()->SourceSize();
9884 PrintF(
"Timing results:\n");
9886 for (
int i = 0; i < timing_.length(); ++i) {
9890 for (
int i = 0; i < names_.length(); ++i) {
9891 PrintF(
"%30s", names_[i]);
9892 double ms =
static_cast<double>(timing_[i]) / 1000;
9893 double percent =
static_cast<double>(timing_[i]) * 100 / sum;
9894 PrintF(
" - %7.3f ms / %4.1f %% ", ms, percent);
9896 unsigned size = sizes_[i];
9897 double size_percent =
static_cast<double>(size) * 100 / total_size_;
9898 PrintF(
" %8u bytes / %4.1f %%\n", size, size_percent);
9900 double source_size_in_kb =
static_cast<double>(source_size_) / 1024;
9901 double normalized_time = source_size_in_kb > 0
9902 ? (
static_cast<double>(sum) / 1000) / source_size_in_kb
9904 double normalized_bytes = source_size_in_kb > 0
9905 ? total_size_ / source_size_in_kb
9907 PrintF(
"%30s - %7.3f ms %7.3f bytes\n",
"Sum",
9908 normalized_time, normalized_bytes);
9909 PrintF(
"---------------------------------------------------------------\n");
9910 PrintF(
"%30s - %7.3f ms (%.1f times slower than full code gen)\n",
9912 static_cast<double>(total_) / 1000,
9913 static_cast<double>(total_) / full_code_gen_);
9918 if (name == HPhase::kFullCodeGen) {
9919 full_code_gen_ += ticks;
9920 }
else if (name == HPhase::kTotal) {
9923 total_size_ += size;
9924 for (
int i = 0; i < names_.length(); ++i) {
9925 if (names_[i] == name) {
9926 timing_[i] += ticks;
9938 const char*
const HPhase::kFullCodeGen =
"Full code generator";
9939 const char*
const HPhase::kTotal =
"Total";
9942 void HPhase::Begin(
const char* name,
9945 LAllocator* allocator) {
9949 allocator_ = allocator;
9950 if (allocator !=
NULL && chunk_ ==
NULL) {
9951 chunk_ = allocator->chunk();
9953 if (FLAG_hydrogen_stats) start_ =
OS::Ticks();
9958 void HPhase::End()
const {
9959 if (FLAG_hydrogen_stats) {
9967 if (FLAG_trace_hydrogen &&
9968 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) !=
NULL) {
9971 if (allocator_ !=
NULL) {
9977 if (graph_ !=
NULL) graph_->Verify(
false);
9978 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)
TypeFeedbackId test_id() const
#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)
bool IsDeoptimizing() const
HBasicBlock * if_true() const
GVNFlagSet gvn_flags() const
Handle< Map > GetCompareMap(CompareOperation *expr)
VariableDeclaration * function() const
bool IsExternalArrayElementsKind(ElementsKind kind)
virtual void ReturnInstruction(HInstruction *instr, BailoutId ast_id)
bool Contains(const T &elm) const
void DeadCodeElimination()
void set_entry(HEnterInlined *entry)
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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra 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 and VFP2 instructions(ARM only)") DEFINE_bool(enable_vfp2
virtual void ReturnControl(HControlInstruction *instr, BailoutId ast_id)
HValueMap * Copy(Zone *zone) const
void PrintF(const char *format,...)
virtual void ReturnControl(HControlInstruction *instr, BailoutId ast_id)
void set_block_id(int id)
virtual HValue * Canonicalize()
virtual void SetDehoisted(bool is_dehoisted)=0
static uint32_t encode(boolvalue)
HInstruction * previous() const
static Smi * FromInt(int value)
static const char * Name(Value tok)
Representation from() const
static bool MakeCode(CompilationInfo *info)
HEnvironment * CopyForInlining(Handle< JSFunction > target, int arguments, FunctionLiteral *function, HConstant *undefined, CallKind call_kind, InliningKind inlining_kind) const
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
InliningKind inlining_kind() const
bool Dominates(HBasicBlock *other) const
HBasicBlock * block() const
static Handle< T > cast(Handle< S > that)
void set_use_optimistic_licm(bool value)
static Representation Integer32()
void Insert(BoundsCheckKey *key, BoundsCheckBbData *data, Zone *zone)
static bool Analyze(CompilationInfo *info)
HConstant * GetConstant1()
FunctionState(HGraphBuilder *owner, CompilationInfo *info, TypeFeedbackOracle *oracle, InliningKind inlining_kind)
bool HasIllegalRedeclaration() const
Expression * condition() const
void SetArgumentsObject(HArgumentsObject *object)
virtual void ReturnInstruction(HInstruction *instr, BailoutId ast_id)=0
static HCheckInstanceType * NewIsString(HValue *value, Zone *zone)
void Finish(HControlInstruction *last)
HInstruction * first() const
static TypeInfo Unknown()
#define DECLARE_FLAG(type)
HEnvironment * arguments_environment()
virtual void ReturnInstruction(HInstruction *instr, BailoutId ast_id)
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()
HBasicBlock * FirstSuccessor()
static LifetimePosition FromInstructionIndex(int index)
HBasicBlock * dominator() const
static const int kMaxLiteralDepth
void SetExpressionStackAt(int index_from_top, HValue *value)
virtual void ReturnControl(HControlInstruction *instr, BailoutId ast_id)=0
virtual int OperandCount()
FrameType frame_type() const
bool CheckArgumentsPhiUses()
HRangeAnalysis(HGraph *graph)
static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags)
Uint32Analysis(Zone *zone)
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)
BoundsCheckBbData(BoundsCheckKey *key, int32_t lower_offset, int32_t upper_offset, HBasicBlock *bb, HBoundsCheck *lower_check, HBoundsCheck *upper_check, BoundsCheckBbData *next_in_bb, BoundsCheckBbData *father_in_dt)
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()
static HInstruction * NewHMod(Zone *zone, HValue *context, HValue *left, HValue *right)
const ZoneList< HBasicBlock * > * predecessors() 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
virtual HValue * OperandAt(int index) const
void DetachLoopInformation()
bool HasPredecessor() const
TypeInfo IncrementType(CountOperation *expr)
static Representation Double()
HEnvironment * CopyAsLoopHeader(HBasicBlock *block) const
virtual void ReturnValue(HValue *value)
FunctionState * function_state() const
bool has_osr_loop_entry()
int GetMaximumValueID() const
bool Equals(const Representation &other)
bool ContainsAnyOf(const EnumSet &set) 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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra 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 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage including flags
int parameter_count() const
bool IsFastElementsKind(ElementsKind kind)
Representation representation() const
ZoneList< HUnknownOSRValue * > * osr_values()
Handle< String > name() const
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
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)
int ContextChainLength(Scope *scope)
void Add(Vector< const char > format, Vector< FmtElm > elms)
HConstant * GetConstantFalse()
bool Covers(LifetimePosition position)
virtual BailoutId ContinueId() const =0
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)
virtual int OperandCount()=0
bool ExpressionStackIsEmpty() const
VariableProxy * proxy() const
void set_arguments_pushed()
bool Equals(HValue *other)
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
BailoutId osr_ast_id() const
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)
Variable * arguments() const
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)
static BailoutId Declarations()
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)
HBasicBlock * loop_header()
#define GVN_TRACKED_FLAG_LIST(V)
HArgumentsElements * arguments_elements()
void EliminateUnreachablePhis()
void set_undefined_constant(HConstant *constant)
void RecordUint32Instruction(HInstruction *instr)
static HTracer * Instance()
static HInstruction * NewHSub(Zone *zone, HValue *context, HValue *left, HValue *right)
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
GvnBasicBlockState * next_in_dominator_tree_traversal(Zone *zone, HBasicBlock **dominator)
void AddInput(HValue *value)
UseInterval * first_interval() const
CompilationInfo * info() 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)
bool IsLexicalVariableMode(VariableMode mode)
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
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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra 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 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random generator(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer
virtual void ReturnInstruction(HInstruction *instr, BailoutId ast_id)
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 BailoutId FunctionEntry()
static Value InvertCompareOp(Value op)
bool Contains(int n) const
HInstruction * last() const
TypeInfo CompareType(CompareOperation *expr)
static bool IsEqualityOp(Value op)
SmartArrayPointer< char > GetGVNFlagsString(GVNFlagSet flags)
void MarkDeoptimizeOnUndefined()
virtual void ReturnControl(HControlInstruction *instr, BailoutId ast_id)
void ComputeMinusZeroChecks()
static ScopeInfo * Empty()
HStackCheckEliminator(HGraph *graph)
void AddSimulate(BailoutId ast_id)
LOperand * FirstHint() const
BoundsCheckBbData * FatherInDominatorTree() const
void RecordDeletedPhi(int merge_index)
virtual HValue * GetKey()=0
Handle< JSFunction > closure() const
virtual void PrintTo(StringStream *stream)
bool IsDeclaredVariableMode(VariableMode mode)
activate correct semantics for inheriting readonliness false
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 SetJoinId(BailoutId ast_id)
void AddEnvironmentValue(HValue *value, Zone *zone)
virtual intptr_t Hashcode()
HBasicBlock * CreateBasicBlock()
bool IsInlineReturnTarget() const
static int SizeFor(int length)
TypeInfo BinaryType(BinaryOperation *expr)
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,...)
HLoopInformation * loop()
HArgumentsObject * GetArgumentsObject() const
const ZoneList< HBasicBlock * > * blocks() const
virtual void SetSuccessorAt(int i, HBasicBlock *block)=0
int first_instruction_index() const
HBasicBlock * BasicBlock() const
Representation to() const
#define CHECK_ALIVE(call)
PostorderProcessor * PerformStep(Zone *zone, BitVector *visited, ZoneList< HBasicBlock * > *order)
UsePosition * first_pos() const
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 set_bailout_reason(const char *reason)
void SetOperandAt(int index, HValue *value)
void AddSimulate(BailoutId ast_id)
HBasicBlock * SecondSuccessor()
static PostorderProcessor * CreateEntryProcessor(Zone *zone, HBasicBlock *block, BitVector *visited)
void FinishExit(HControlInstruction *instruction)
ElementsKind GetInitialFastElementsKind()
bool CheckFlag(Flag f) const
FunctionSorter(int index, int ticks, int ast_length, int src_length)
HGraph(CompilationInfo *info)
Handle< SharedFunctionInfo > shared_info() const
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)
void Goto(HBasicBlock *block, FunctionState *state=NULL)
HGraphBuilder(CompilationInfo *info, TypeFeedbackOracle *oracle)
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)
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)
virtual void ReturnValue(HValue *value)
void SetBlock(HBasicBlock *block)
void PrintTo(StringStream *stream)
static Handle< SharedFunctionInfo > BuildFunctionInfo(FunctionLiteral *node, Handle< Script > script)
PostorderProcessor * child()
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)
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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra 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 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
HBasicBlock * CreateJoin(HBasicBlock *first, HBasicBlock *second, BailoutId join_id)
#define ASSERT_NE(v1, v2)
virtual HValue * OperandAt(int index) const =0
static const uint32_t kDefaultHashMapCapacity
HConstant * GetConstantHole()
CompilationInfo * compilation_info()
static const int kEnumCacheBridgeCacheIndex
const T & at(int index) const
int update_type_change_checksum(int delta)
OptimizingCompilerThread * optimizing_compiler_thread()
void ComputeSafeUint32Operations()
PostorderProcessor * parent()
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
void set_ast_id(BailoutId id)
HBasicBlock * if_false() const
static const char * AllocationIndexToString(int index)
static bool HasCustomCallGenerator(Handle< JSFunction > function)
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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra 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 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
void EliminateRedundantBoundsChecks()
static GVNFlag ChangesFlagFromInt(int x)
static const int kMaxInliningLevels
bool IsSymbolCompare(CompareOperation *expr)
void TraceHydrogen(const char *name, HGraph *graph)
void Bailout(const char *reason)
bool has_global_object() const
BailoutId EntryId() const
void AddIndirectUsesTo(int *use_count)
char * StrDup(const char *str)
const ZoneList< HPhi * > * phis() const
void TraceCompilation(FunctionLiteral *function)
void AssignLoopSuccessorDominators()
bool HasInteger32Value() 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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
static Representation None()
static const int kValueOffset
bool is_function_scope() const
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)
virtual void SetKey(HValue *key)=0
VariableMode mode() 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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra 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 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage including flags
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()
TypeFeedbackOracle * oracle() const
#define CHECK_BAILOUT(call)
virtual void ReturnValue(HValue *value)=0
TypeInfo UnaryType(UnaryOperation *expr)
HBoundsCheck * UpperCheck() const
HBoundsCheck * LowerCheck() const
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
bool Optimize(SmartArrayPointer< char > *bailout_reason)
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)
void AddLeaveInlined(HValue *return_value, FunctionState *state)
friend class FunctionState
HEnvironment * CopyWithoutHistory() const
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kInstanceClassNameOffset flag
static JSFunction * cast(Object *obj)