21 static inline void Trace(
const char* msg, ...) {
22 if (FLAG_trace_turbo_scheduler) {
24 va_start(arguments, msg);
57 Node* node =
queue_.front();
72 void FixNode(BasicBlock* block, Node* node) {
90 switch (node->opcode()) {
92 case IrOpcode::kMerge:
95 case IrOpcode::kBranch:
104 switch (node->opcode()) {
105 case IrOpcode::kLoop:
106 case IrOpcode::kMerge:
109 case IrOpcode::kBranch:
113 case IrOpcode::kReturn:
125 Trace(
"Create block B%d for #%d:%s\n", block->id(), node->id(),
126 node->op()->mnemonic());
147 for (
UseIter i = node->uses().begin();
i != node->uses().end(); ++
i) {
148 if ((*i)->opcode() == true_opcode) {
152 if ((*i)->opcode() == false_opcode) {
175 BasicBlock* successor_blocks[2];
179 TraceConnect(branch, branch_block, successor_blocks[0]);
180 TraceConnect(branch, branch_block, successor_blocks[1]);
183 successor_blocks[1]);
191 for (
InputIter j = merge->inputs().begin(); j != merge->inputs().end();
194 if ((*j)->opcode() != IrOpcode::kReturn) {
211 Trace(
"Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(),
214 Trace(
"Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(),
215 block->id(), succ->id());
231 scheduled_nodes_(zone),
232 schedule_root_nodes_(zone),
233 node_data_(graph_->NodeCount(), DefaultSchedulerData(), zone),
234 has_floating_control_(
false) {}
239 bool had_floating_control =
false;
242 schedule =
new (graph->
zone())
244 Scheduler scheduler(&tmp_zone, graph, schedule);
256 }
while (had_floating_control);
265 switch (node->opcode()) {
266 case IrOpcode::kParameter:
271 case IrOpcode::kEffectPhi: {
276 #define DEFINE_FLOATING_CONTROL_CASE(V) case IrOpcode::k##V:
278 #undef DEFINE_FLOATING_CONTROL_CASE
285 Trace(
"Floating control found: #%d:%s\n", node->id(),
286 node->op()->mnemonic());
300 Trace(
"---------------- CREATING CFG ------------------\n");
313 if (b1_rpo < b2_rpo) {
326 Trace(
"------------ IMMEDIATE BLOCK DOMINATORS -----------\n");
330 BasicBlock::Predecessors::iterator current_pred =
331 current_rpo->predecessors().begin();
332 BasicBlock::Predecessors::iterator end =
333 current_rpo->predecessors().end();
334 DCHECK(current_pred != end);
335 BasicBlock* dominator = *current_pred;
340 while (current_pred != end) {
342 BasicBlock* pred = *current_pred;
348 current_rpo->dominator_ = dominator;
349 Trace(
"Block %d's idom is %d\n", current_rpo->id(), dominator->id());
368 max_rpo = block->rpo_number_;
373 Trace(
"Preschedule #%d:%s minimum_rpo = %d\n", node->id(),
374 node->op()->mnemonic(), max_rpo);
383 for (
InputIter i = node->inputs().begin();
i != node->inputs().end();
386 if (control_rpo > max_rpo) {
387 max_rpo = control_rpo;
394 Trace(
"Postschedule #%d:%s minimum_rpo = %d\n", node->id(),
395 node->op()->mnemonic(), max_rpo);
411 Trace(
"------------------- SCHEDULE EARLY ----------------\n");
413 int fixpoint_count = 0;
421 Trace(
"It took %d iterations to determine fixpoint\n", fixpoint_count);
436 Trace(
" Scheduling fixed position node #%d:%s\n", node->id(),
437 node->op()->mnemonic());
440 opcode == IrOpcode::kParameter
458 Trace(
" Use count of #%d:%s (used by #%d:%s)++ = %d\n",
to->id(),
459 to->op()->mnemonic(), from->id(), from->op()->mnemonic(),
471 Trace(
"------------------- PREPARE USES ------------------\n");
495 Trace(
"Testing for schedule eligibility for #%d:%s = %s\n", node->id(),
496 node->op()->mnemonic(), eligible ?
"true" :
"false");
501 BasicBlock* block =
NULL;
502 for (Node::Uses::iterator
i = node->uses().begin();
i != node->uses().end();
505 block = block ==
NULL ? use_block : use_block ==
NULL
514 "Schedule late conservative for #%d:%s is B%d at loop depth %d, "
515 "minimum_rpo = %d\n",
516 node->id(), node->op()->mnemonic(), block->id(), block->loop_depth_,
521 BasicBlock* hoist_block = block;
522 while (hoist_block !=
NULL && hoist_block->rpo_number_ >= min_rpo) {
523 if (hoist_block->loop_depth_ < block->loop_depth_) {
525 Trace(
" hoisting #%d:%s to block %d\n", node->id(),
526 node->op()->mnemonic(), block->id());
529 hoist_block = hoist_block->loop_header();
530 if (hoist_block !=
NULL) {
531 BasicBlock* pre_header = hoist_block->dominator_;
533 *hoist_block->predecessors().begin() == pre_header);
535 " hoist to pre-header B%d of loop header B%d, depth would be %d\n",
536 pre_header->id(), hoist_block->id(), pre_header->loop_depth_);
537 hoist_block = pre_header;
548 Node*
use = edge.from();
550 if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) {
553 int index = edge.index();
555 Trace(
" input@%d into a fixed phi #%d:%s\n", index,
use->id(),
556 use->op()->mnemonic());
558 opcode = merge->opcode();
559 DCHECK(opcode == IrOpcode::kMerge || opcode == IrOpcode::kLoop);
565 Trace(
" must dominate use #%d:%s in B%d\n",
use->id(),
566 use->op()->mnemonic(), result->id());
576 for (
InputIter i = node->inputs().begin();
i != node->inputs().end(); ++
i) {
580 if (FLAG_trace_turbo_scheduler) {
581 Trace(
" Use count for #%d:%s (used by #%d:%s)-- = %d\n", (*i)->id(),
582 (*i)->op()->mnemonic(),
i.edge().from()->id(),
585 Trace(
" newly eligible #%d:%s\n", (*i)->id(),
586 (*i)->op()->mnemonic());
598 Trace(
"------------------- SCHEDULE LATE -----------------\n");
599 if (FLAG_trace_turbo_scheduler) {
603 Trace(
"#%d:%s ", (*i)->id(), (*i)->op()->mnemonic());
616 &schedule_late_visitor);
634 Trace(
"Connecting floating control...\n");
640 for (
int i = max - 1;
i >= 0;
i--) {
645 bool one_placed =
false;
646 for (
int j =
static_cast<int>(block->nodes_.size()) - 1; j >= 0; j--) {
647 Node* node = block->nodes_[j];
651 Trace(
" Floating control #%d:%s was scheduled in B%d\n", node->id(),
652 node->op()->mnemonic(), block->id());
664 Node* block_start = block->nodes_[0];
669 Node* control_succ =
NULL;
670 for (
UseIter i = block_start->uses().begin();
i != block_start->uses().end();
672 Node::Edge edge =
i.edge();
676 control_succ = edge.from();
677 control_succ->ReplaceInput(edge.index(), end);
681 Trace(
" Inserting floating control end %d:%s between %d:%s -> %d:%s\n",
682 end->id(), end->op()->mnemonic(), control_succ->id(),
683 control_succ->op()->mnemonic(), block_start->id(),
684 block_start->op()->mnemonic());
693 while (!queue.empty()) {
694 Node* node = queue.front();
696 Trace(
" Search #%d:%s for control subgraph start\n", node->id(),
697 node->op()->mnemonic());
700 Node* input = node->InputAt(
i);
721 Trace(
" Connecting floating control start %d:%s to %d:%s\n", start->id(),
722 start->op()->mnemonic(), block_start->id(),
723 block_start->op()->mnemonic());
752 l->block->rpo_number_ =
static_cast<int>(final_order->size());
753 final_order->push_back(l->block);
775 if (child->rpo_number_ == unvisited) {
776 stack[depth].
block = child;
777 stack[depth].
index = 0;
788 ZoneList<std::pair<BasicBlock*, int> >* backedges) {
790 memset(loops, 0, num_loops *
sizeof(
LoopInfo));
794 for (
int i = 0;
i < backedges->length();
i++) {
795 BasicBlock* member = backedges->at(
i).first;
796 BasicBlock* header = member->SuccessorAt(backedges->at(
i).second);
797 int loop_num = header->loop_end_;
798 if (loops[loop_num].header ==
NULL) {
799 loops[loop_num].
header = header;
803 int queue_length = 0;
804 if (member != header) {
807 if (!loops[loop_num].members->Contains(member->id())) {
810 queue[queue_length++].
block = member;
815 while (queue_length > 0) {
816 BasicBlock* block = queue[--queue_length].
block;
817 for (
int i = 0;
i < block->PredecessorCount();
i++) {
818 BasicBlock* pred = block->PredecessorAt(
i);
819 if (pred != header) {
820 if (!loops[loop_num].members->Contains(pred->id())) {
822 queue[queue_length++].
block = pred;
833 static void PrintRPO(
int num_loops, LoopInfo* loops,
BasicBlockVector* order) {
834 PrintF(
"-- RPO with %d loops ", num_loops);
837 for (
int i = 0;
i < num_loops;
i++) {
839 PrintF(
"B%d", loops[
i].header->id());
845 for (
int i = 0; i < static_cast<int>(order->size());
i++) {
846 BasicBlock* block = (*order)[
i];
847 int bid = block->id();
849 for (
int i = 0;
i < num_loops;
i++) {
850 bool membership = loops[
i].members->Contains(bid);
851 bool range = loops[
i].header->LoopContains(block);
852 PrintF(membership ?
" |" :
" ");
853 PrintF(range ?
"x" :
" ");
856 if (block->loop_end_ >= 0) {
857 PrintF(
" range: [%d, %d)", block->rpo_number_, block->loop_end_);
864 static void VerifySpecialRPO(
int num_loops, LoopInfo* loops,
866 DCHECK(order->size() > 0);
867 DCHECK((*order)[0]->
id() == 0);
869 for (
int i = 0;
i < num_loops;
i++) {
870 LoopInfo* loop = &loops[
i];
871 BasicBlock* header = loop->header;
874 DCHECK(header->rpo_number_ >= 0);
875 DCHECK(header->rpo_number_ <
static_cast<int>(order->size()));
876 DCHECK(header->loop_end_ >= 0);
877 DCHECK(header->loop_end_ <=
static_cast<int>(order->size()));
878 DCHECK(header->loop_end_ > header->rpo_number_);
882 BlockList* l = loop->start;
886 if (l ==
NULL || l == loop->end) {
887 end_found = (loop->end == l);
891 DCHECK(l->block->rpo_number_ == links + loop->header->rpo_number_);
894 DCHECK(links <
static_cast<int>(2 * order->size()));
897 DCHECK(links == (header->loop_end_ - header->rpo_number_));
902 for (
int j = 0; j < static_cast<int>(order->size()); j++) {
903 BasicBlock* block = order->at(j);
904 DCHECK(block->rpo_number_ == j);
905 if (j < header->rpo_number_ || j >= header->loop_end_) {
906 DCHECK(!loop->members->Contains(block->id()));
908 if (block == header) {
909 DCHECK(!loop->members->Contains(block->id()));
911 DCHECK(loop->members->Contains(block->id()));
935 Zone* zone = &tmp_zone;
936 Trace(
"------------- COMPUTING SPECIAL RPO ---------------\n");
946 BasicBlock* entry = schedule->
start();
951 while (stack_depth > 0) {
952 int current = stack_depth - 1;
955 if (frame->
index < frame->
block->SuccessorCount()) {
957 BasicBlock* succ = frame->
block->SuccessorAt(frame->
index++);
962 std::pair<BasicBlock*, int>(frame->
block, frame->
index - 1), zone);
963 if (succ->loop_end_ < 0) {
965 succ->loop_end_ = num_loops++;
974 order = order->
Add(zone, frame->
block);
982 if (num_loops != 0) {
989 LoopInfo* loop = entry->IsLoopHeader() ? &loops[entry->loop_end_] :
NULL;
997 while (stack_depth > 0) {
999 BasicBlock* block = frame->
block;
1000 BasicBlock* succ =
NULL;
1002 if (frame->
index < block->SuccessorCount()) {
1004 succ = block->SuccessorAt(frame->
index++);
1005 }
else if (block->IsLoopHeader()) {
1011 loop->
start = order->
Add(zone, block);
1022 int outgoing_index = frame->
index - block->SuccessorCount();
1023 LoopInfo* info = &loops[block->loop_end_];
1026 outgoing_index < info->outgoing->length()) {
1044 if (succ->IsLoopHeader()) {
1046 DCHECK(succ->loop_end_ >= 0 && succ->loop_end_ < num_loops);
1047 LoopInfo* next = &loops[succ->loop_end_];
1055 if (block->IsLoopHeader()) {
1057 LoopInfo* info = &loops[block->loop_end_];
1059 if (l->next == info->
end) {
1065 order = info->
start;
1068 order = order->
Add(zone, block);
1083 BasicBlock* current_header =
NULL;
1087 BasicBlock* current = *
i;
1088 current->loop_header_ = current_header;
1089 if (current->IsLoopHeader()) {
1091 current_loop = &loops[current->loop_end_];
1093 current->loop_end_ = end ==
NULL ?
static_cast<int>(final_order->size())
1094 : end->
block->rpo_number_;
1095 current_header = current_loop->
header;
1096 Trace(
"B%d is a loop header, increment loop depth to %d\n", current->id(),
1099 while (current_header !=
NULL &&
1100 current->rpo_number_ >= current_header->loop_end_) {
1101 DCHECK(current_header->IsLoopHeader());
1103 current_loop = current_loop->
prev;
1104 current_header = current_loop ==
NULL ?
NULL : current_loop->
header;
1108 current->loop_depth_ = loop_depth;
1109 if (current->loop_header_ ==
NULL) {
1110 Trace(
"B%d is not in a loop (depth == %d)\n", current->id(),
1111 current->loop_depth_);
1113 Trace(
"B%d has loop header B%d, (depth == %d)\n", current->id(),
1114 current->loop_header_->id(), current->loop_depth_);
1119 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order);
1120 VerifySpecialRPO(num_loops, loops, final_order);
static void VPrint(const char *format, va_list args)
bool Contains(int i) const
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Isolate * isolate() const
void BuildBlocks(Node *node)
void TraceConnect(Node *node, BasicBlock *block, BasicBlock *succ)
void BuildBlockForNode(Node *node)
void CollectSuccessorBlocks(Node *node, BasicBlock **buffer, IrOpcode::Value true_opcode, IrOpcode::Value false_opcode)
CFGBuilder(Zone *zone, Scheduler *scheduler)
void ConnectReturn(Node *ret)
void BuildBlocksForSuccessors(Node *node, IrOpcode::Value a, IrOpcode::Value b)
ZoneQueue< Node * > queue_
void CollectSuccessorProjections(Node *node, Node **buffer, IrOpcode::Value true_opcode, IrOpcode::Value false_opcode)
void FixNode(BasicBlock *block, Node *node)
void ConnectMerge(Node *merge)
void ConnectBlocks(Node *node)
void ConnectBranch(Node *branch)
static void Visit(GenericGraphBase *graph, Zone *zone, RootIterator root_begin, RootIterator root_end, Visitor *visitor)
void VisitNodeInputsFromEnd(Visitor *visitor)
static bool IsControlOpcode(Value val)
static int PastControlIndex(Node *node)
static bool IsControlEdge(Node::Edge edge)
static int FirstControlIndex(Node *node)
static Node * GetControlInput(Node *node, int index=0)
GenericGraphVisit::Control Pre(Node *node)
PrepareUsesVisitor(Scheduler *scheduler)
void PostEdge(Node *from, int index, Node *to)
bool has_changed_rpo_constraints_
ScheduleEarlyNodeVisitor(Scheduler *scheduler)
GenericGraphVisit::Control Pre(Node *node)
GenericGraphVisit::Control Post(Node *node)
GenericGraphVisit::Control Pre(Node *node)
BasicBlock * GetBlockForUse(Node::Edge edge)
void ScheduleNode(BasicBlock *block, Node *node)
ScheduleLateNodeVisitor(Scheduler *scheduler)
void PlanNode(BasicBlock *block, Node *node)
void AddGoto(BasicBlock *block, BasicBlock *succ)
void AddReturn(BasicBlock *block, Node *input)
int BasicBlockCount() const
BasicBlockVector all_blocks_
BasicBlock * NewBasicBlock()
void AddBranch(BasicBlock *block, Node *branch, BasicBlock *tblock, BasicBlock *fblock)
void AddNode(BasicBlock *block, Node *node)
bool IsScheduled(Node *node)
BasicBlock * block(Node *node) const
BasicBlockVector * rpo_order()
BasicBlockVector rpo_order_
Scheduler(Zone *zone, Graph *graph, Schedule *schedule)
friend class ScheduleLateNodeVisitor
SchedulerData * GetData(Node *node)
bool has_floating_control_
NodeVectorVector scheduled_nodes_
void GenerateImmediateDominatorTree()
bool ConnectFloatingControl()
NodeVector schedule_root_nodes_
static BasicBlockVector * ComputeSpecialRPO(Schedule *schedule)
int GetRPONumber(BasicBlock *block)
void ConnectFloatingControlSubgraph(BasicBlock *block, Node *node)
Placement GetPlacement(Node *node)
SchedulerData DefaultSchedulerData()
static Schedule * ComputeSchedule(Graph *graph)
BasicBlock * GetCommonDominator(BasicBlock *b1, BasicBlock *b2)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to use(in kBytes)") DEFINE_INT(max_stack_trace_source_length
enable harmony numeric enable harmony object literal extensions true
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define CHECK_EQ(expected, value)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
static const int kBlockOnStack
Node::Uses::iterator UseIter
ZoneVector< BasicBlock * > BasicBlockVector
static const int kBlockUnvisited2
static int Push(SpecialRPOStackFrame *stack, int depth, BasicBlock *child, int unvisited)
static void Trace(const char *msg,...)
BasicBlockVector::iterator BasicBlockVectorIter
static const int kBlockUnvisited1
static LoopInfo * ComputeLoopInfo(Zone *zone, SpecialRPOStackFrame *queue, int num_loops, int num_blocks, ZoneList< std::pair< BasicBlock *, int > > *backedges)
NodeVector::iterator NodeVectorIter
Node::Inputs::iterator InputIter
NodeVector::reverse_iterator NodeVectorRIter
static const int kBlockVisited2
NodeVectorVector::iterator NodeVectorVectorIter
static const int kBlockVisited1
void PrintF(const char *format,...)
Debugger support for the V8 JavaScript engine.
#define CONTROL_OP_LIST(V)
#define DEFINE_FLOATING_CONTROL_CASE(V)
void Serialize(BasicBlockVector *final_order)
BlockList * Add(Zone *zone, BasicBlock *b)
void AddOutgoing(Zone *zone, BasicBlock *block)
ZoneList< BasicBlock * > * outgoing
bool is_floating_control_
bool is_connected_control_