Skip to content

Commit

Permalink
Mark in-try-block more eagerly
Browse files Browse the repository at this point in the history
  • Loading branch information
kasperl committed Oct 23, 2024
1 parent bdede84 commit 9e4bc3a
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 22 deletions.
8 changes: 3 additions & 5 deletions src/compiler/propagation/concrete_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class ConcreteType {
explicit ConcreteType(unsigned id)
: data_((id << 1) | 1) {}

explicit ConcreteType(BlockTemplate* block)
: data_(reinterpret_cast<uword>(block)) {}

static ConcreteType any() { return ConcreteType(); }

bool is_block() const {
Expand Down Expand Up @@ -72,11 +75,6 @@ class ConcreteType {
uword data_;

ConcreteType() : data_(ANY) {}

explicit ConcreteType(BlockTemplate* block)
: data_(reinterpret_cast<uword>(block)) {}

friend class BlockTemplate;
};

} // namespace toit::compiler
Expand Down
29 changes: 21 additions & 8 deletions src/compiler/propagation/type_propagator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,7 @@ void TypePropagator::call_method(MethodTemplate* caller,
// and megamorphic types that tend to blow up the analysis.
TypeSet type = stack->local(arity - index);
if (type.is_block()) {
BlockTemplate* block = type.block();
arguments.push_back(block->pass_as_argument(scope));
arguments.push_back(ConcreteType(type.block()));
call_method(caller, scope, site, target, arguments);
arguments.pop_back();
} else if (type.size(words_per_type_) > 5) {
Expand All @@ -427,14 +426,22 @@ void TypePropagator::propagate_blocks(MethodTemplate* caller,
TypeScope* scope,
int arity,
std::vector<Worklist*>& worklists) {
TypeStack* stack = scope->top();
int count = 0;
for (int i = 0; i < arity; i++) {
TypeSet type = stack->local(arity - i - 1);
if (!type.is_block()) continue;
BlockTemplate* block = type.block();
if (scope->is_in_try_block()) block->mark_invoked_from_try_block();
count++;
}

// Propagate types through all locally-defined block arguments.
// We cannot handle block arguments outside of ordinary methods,
// so if the caller isn't set, we analyzing a call to a method from
// an entry stub of sorts.
if (!caller) return;

if (!caller || count == 0) return;
Set<BlockTemplate*> blocks;
TypeStack* stack = scope->top();
for (int i = 0; i < arity; i++) {
TypeSet type = stack->local(arity - i - 1);
if (!type.is_block()) continue;
Expand Down Expand Up @@ -1609,19 +1616,25 @@ TypeSet BlockTemplate::invoke(TypePropagator* propagator, TypeScope* scope, uint
for (auto it : users_) propagator->enqueue(it);
}
if (scope->is_in_try_block()) {
invoke_from_try_block();
mark_invoked_from_try_block();
}
return result_.use(propagator, scope->method(), site);
}

void BlockTemplate::invoke_from_try_block() {
void BlockTemplate::mark_invoked_from_try_block() {
if (is_invoked_from_try_block_) return;
is_invoked_from_try_block_ = true;

// If the block hasn't been invoked yet, we wait for it
// to be invoked before we enqueue the surrounding method
// for analysis again.
if (!is_invoked_) return;

// If we find that this block may have been invoked from
// within a try-block, we re-analyze the surrounding
// method, so we can track stores to outer locals that
// may be visible because of caught exceptions or
// stopped unwinding.
is_invoked_from_try_block_ = true;
for (auto it : users_) {
it->propagator()->enqueue(it);
}
Expand Down
10 changes: 1 addition & 9 deletions src/compiler/propagation/type_propagator.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,14 +209,8 @@ class BlockTemplate {
bool matches(Method target, int level, MethodTemplate* user) const;
void use(TypePropagator* propagator, MethodTemplate* user);

ConcreteType pass_as_argument(TypeScope* scope) {
// If we pass a block as an argument inside a try-block, we
// conservatively assume that it is going to be invoked.
if (scope->is_in_try_block()) invoke_from_try_block();
return ConcreteType(this);
}

TypeSet invoke(TypePropagator* propagator, TypeScope* scope, uint8* site);
void mark_invoked_from_try_block();

void ret(TypePropagator* propagator, TypeStack* stack) {
TypeSet top = stack->local(0);
Expand Down Expand Up @@ -254,8 +248,6 @@ class BlockTemplate {
// using it to determine if a BlockTemplate can be reused by
// another user in the BlockTemplate::matches function.
MethodTemplate* last_user_ = null;

void invoke_from_try_block();
};

} // namespace toit::compiler
Expand Down

0 comments on commit 9e4bc3a

Please sign in to comment.