// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #ifndef RUNTIME_VM_COMPILER_FRONTEND_FLOW_GRAPH_BUILDER_H_ #define RUNTIME_VM_COMPILER_FRONTEND_FLOW_GRAPH_BUILDER_H_ #if defined(DART_PRECOMPILED_RUNTIME) #error "AOT runtime should not use compiler sources (including header files)" #endif // defined(DART_PRECOMPILED_RUNTIME) #include "platform/assert.h" #include "platform/globals.h" #include "vm/allocation.h" #include "vm/compiler/backend/flow_graph.h" #include "vm/compiler/backend/il.h" #include "vm/growable_array.h" #include "vm/raw_object.h" namespace dart { // A class to collect the exits from an inlined function during graph // construction so they can be plugged into the caller's flow graph. class InlineExitCollector : public ZoneAllocated { public: InlineExitCollector(FlowGraph* caller_graph, Definition* call) : caller_graph_(caller_graph), call_(call), exits_(4) {} void AddExit(ReturnInstr* exit); void Union(const InlineExitCollector* other); // Before replacing a call with a graph, the outer environment needs to be // attached to each instruction in the callee graph and the caller graph // needs to have its block and instruction ID state updated. // Additionally we need to remove all unreachable exits from the list of // collected exits. void PrepareGraphs(FlowGraph* callee_graph); // Inline a graph at a call site. // // Assumes the callee is in SSA with a correct dominator tree and use // lists. // // After inlining the caller graph will have correctly adjusted the use // lists. The block orders will need to be recomputed. void ReplaceCall(BlockEntryInstr* callee_entry); private: struct Data { BlockEntryInstr* exit_block; ReturnInstr* exit_return; }; BlockEntryInstr* ExitBlockAt(intptr_t i) const { ASSERT(exits_[i].exit_block != NULL); return exits_[i].exit_block; } Instruction* LastInstructionAt(intptr_t i) const { return ReturnAt(i)->previous(); } Value* ValueAt(intptr_t i) const { return ReturnAt(i)->value(); } ReturnInstr* ReturnAt(intptr_t i) const { return exits_[i].exit_return; } static int LowestBlockIdFirst(const Data* a, const Data* b); void SortExits(); void RemoveUnreachableExits(FlowGraph* callee_graph); Definition* JoinReturns(BlockEntryInstr** exit_block, Instruction** last_instruction, intptr_t try_index); Zone* zone() const { return caller_graph_->zone(); } FlowGraph* caller_graph_; Definition* call_; GrowableArray exits_; }; bool SimpleInstanceOfType(const AbstractType& type); uword FindDoubleConstant(double value); } // namespace dart #endif // RUNTIME_VM_COMPILER_FRONTEND_FLOW_GRAPH_BUILDER_H_