summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/register_allocator.h
diff options
context:
space:
mode:
authorDavid Brazdil <dbrazdil@google.com>2015-08-20 17:47:48 +0100
committerDavid Brazdil <dbrazdil@google.com>2015-09-14 20:42:58 +0100
commitb022fa1300e6d78639b3b910af0cf85c43df44bb (patch)
tree780c7d6bdee784c2f8248979de348491cfb63b34 /compiler/optimizing/register_allocator.h
parente481c006e8b055a31d9c7cff27f4145e57e3c113 (diff)
downloadart-b022fa1300e6d78639b3b910af0cf85c43df44bb.tar.gz
art-b022fa1300e6d78639b3b910af0cf85c43df44bb.tar.bz2
art-b022fa1300e6d78639b3b910af0cf85c43df44bb.zip
ART: Register allocation and runtime support for try/catch
This patch completes a series of CLs that add support for try/catch in the Optimizing compiler. With it, Optimizing can compile all methods containing try/catch, provided they don't contain catch loops. Future work will focus on improving performance of the generated code. SsaLivenessAnalysis was updated to propagate liveness information of instructions live at catch blocks, and to keep location information on instructions which may be caught by catch phis. RegisterAllocator was extended to spill values used after catch, and to allocate spill slots for catch phis. Catch phis generated for the same vreg share a spill slot as the raw value must be the same. Location builders and slow paths were updated to reflect the fact that throwing an exception may not lead to escaping the method. Instruction code generators are forbidden from using of implicit null checks in try blocks as live registers need to be saved before handing over to the runtime. CodeGenerator emits a stack map for each catch block, storing locations of catch phis. CodeInfo and StackMapStream recognize this new type of stack map and store them separate from other stack maps to avoid dex_pc conflicts. After having found the target catch block to deliver an exception to, QuickExceptionHandler looks up the dex register maps at the throwing instruction and the catch block and copies the values over to their respective locations. The runtime-support approach was selected because it allows for the best performance in the normal control-flow path, since no propagation of catch phi values is necessary until the exception is thrown. In addition, it also greatly simplifies the register allocation phase. ConstantHoisting was removed from LICMTest because it instantiated (now abstract) HConstant and was bogus anyway (constants are always in the entry block). Change-Id: Ie31038ad8e3ee0c13a5bbbbaf5f0b3e532310e4e
Diffstat (limited to 'compiler/optimizing/register_allocator.h')
-rw-r--r--compiler/optimizing/register_allocator.h18
1 files changed, 16 insertions, 2 deletions
diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h
index c29fe75921..e0304643e6 100644
--- a/compiler/optimizing/register_allocator.h
+++ b/compiler/optimizing/register_allocator.h
@@ -29,6 +29,7 @@ class HBasicBlock;
class HGraph;
class HInstruction;
class HParallelMove;
+class HPhi;
class LiveInterval;
class Location;
class SsaLivenessAnalysis;
@@ -72,7 +73,8 @@ class RegisterAllocator {
return int_spill_slots_.Size()
+ long_spill_slots_.Size()
+ float_spill_slots_.Size()
- + double_spill_slots_.Size();
+ + double_spill_slots_.Size()
+ + catch_phi_spill_slots_;
}
static constexpr const char* kRegisterAllocatorPassName = "register";
@@ -99,10 +101,17 @@ class RegisterAllocator {
// Update the interval for the register in `location` to cover [start, end).
void BlockRegister(Location location, size_t start, size_t end);
+ void BlockRegisters(size_t start, size_t end, bool caller_save_only = false);
- // Allocate a spill slot for the given interval.
+ // Allocate a spill slot for the given interval. Should be called in linear
+ // order of interval starting positions.
void AllocateSpillSlotFor(LiveInterval* interval);
+ // Allocate a spill slot for the given catch phi. Will allocate the same slot
+ // for phis which share the same vreg. Must be called in reverse linear order
+ // of lifetime positions and ascending vreg numbers for correctness.
+ void AllocateSpillSlotForCatchPhi(HPhi* phi);
+
// Connect adjacent siblings within blocks.
void ConnectSiblings(LiveInterval* interval);
@@ -202,6 +211,11 @@ class RegisterAllocator {
GrowableArray<size_t> float_spill_slots_;
GrowableArray<size_t> double_spill_slots_;
+ // Spill slots allocated to catch phis. This category is special-cased because
+ // (1) slots are allocated prior to linear scan and in reverse linear order,
+ // (2) equivalent phis need to share slots despite having different types.
+ size_t catch_phi_spill_slots_;
+
// Instructions that need a safepoint.
GrowableArray<HInstruction*> safepoints_;