1
%%% -*- erlang-indent-level: 2 -*-
4
%%% Expand virtual gc tests to actual code.
6
-module(hipe_rtl_gctests).
10
{LowLbl, HighLbl} = hipe_rtl_cfg:label_range(CFG),
11
hipe_gensym:set_label(rtl,HighLbl),
12
{LowVar, HighVar} = hipe_rtl_cfg:var_range(CFG),
13
hipe_gensym:set_var(rtl,HighVar),
14
Labels = hipe_rtl_cfg:labels(CFG),
15
CFG1 = expand_gctests(Labels, CFG),
16
CFG2 = hipe_rtl_cfg:label_range_update(CFG1, {LowLbl, hipe_gensym:get_label(rtl)}),
17
hipe_rtl_cfg:var_range_update(CFG2, {LowVar, hipe_gensym:get_var(rtl)}).
19
expand_gctests([], CFG) ->
21
expand_gctests([L|Ls], CFG) ->
22
BB = hipe_rtl_cfg:bb(CFG, L),
23
Code = hipe_bb:code(BB),
24
{NewCode, CFG0} = expand_gc(Code, CFG),
25
CFG1 = hipe_rtl_cfg:bb_update(CFG0, L, hipe_bb:code_update(BB, NewCode)),
26
expand_gctests(Ls, CFG1).
30
expand_gc([I|Is], CFG) ->
31
{CodeRest, CFG0} = expand_gc(Is, CFG),
32
case hipe_rtl:type(I) of
33
gctest -> %% Two new blocks, The rest of this one, and one for the gc
35
ContLabel = hipe_rtl:label_name(hipe_rtl:mk_new_label()),
36
CFG1 = hipe_rtl_cfg:bb_add(CFG0, ContLabel, hipe_bb:mk_bb(CodeRest)),
38
%% Note: the pointer arithmetic is done in bytes,
39
%% but the gc parameter is in words (tagged as fixnum).
40
WordsNeeded = hipe_rtl:gctest_words(I),
41
Tmp = hipe_rtl:mk_new_reg(),
42
{GetHPInsn, HP, _PutHPInsn} = hipe_rtl_arch:heap_pointer(),
43
H_LIMIT = hipe_rtl:mk_reg(hipe_rtl_arch:heap_limit_reg()),
44
GCLabel = hipe_rtl:label_name(hipe_rtl:mk_new_label()),
46
case hipe_rtl:is_reg(WordsNeeded) of
48
true -> %Creates a gctest for a number of words known at runtime
49
HPAmount = hipe_rtl:mk_new_reg(),
50
GCAmount = hipe_rtl:mk_new_var(),
51
Code = [hipe_rtl:mk_alu(HPAmount, WordsNeeded, sll, hipe_rtl:mk_imm(2)),
52
hipe_rtl:mk_alu(Tmp, H_LIMIT, 'sub', HP),
53
hipe_rtl:mk_alu(GCAmount, WordsNeeded, sll, hipe_rtl:mk_imm(4)),
54
hipe_rtl:mk_alu(GCAmount, GCAmount, 'add', hipe_rtl:mk_imm(15)),
55
hipe_rtl:mk_branch(Tmp, 'lt', HPAmount, GCLabel, ContLabel, 0.01)];
56
false -> %Creates a gctest for a fixed number of words
57
GCAmount = hipe_rtl:mk_imm(hipe_tagscheme:mk_fixnum(WordsNeeded)),
58
HPAmount = hipe_rtl:mk_imm(WordsNeeded*4),
60
%% Do the GC overflow test. In the old version,
61
%% if( (Tmp = HP+HPAmount) >= H_LIMIT ) goto GCLabel,
62
%% Tmp could wrap around. The new version below should be safe.
63
Code = [hipe_rtl:mk_alu(Tmp, H_LIMIT, 'sub', HP),
64
hipe_rtl:mk_branch(Tmp, 'lt', HPAmount, GCLabel, ContLabel, 0.01)]
66
GCCode = [hipe_rtl:mk_call([], gc_1, [GCAmount], c, ContLabel, [])],
67
CFG2 = hipe_rtl_cfg:bb_add(CFG1, GCLabel, hipe_bb:mk_bb(GCCode)),
69
{[GetHPInsn | Code], CFG2};