Repository: JuliaLang/julia
File: src/interpreter.c (C)

Code before:
            size_t catch_ip = jl_enternode_catch_dest(stmt);
            if (catch_ip) {
                catch_ip -= 1;
                while (catch_ip < ns) {
                    jl_value_t *phicnode = jl_array_ptr_ref(stmts, catch_ip);
                    if (!jl_is_phicnode(phicnode))
                        break;
                    jl_array_t *values = (jl_array_t*)jl_fieldref_noalloc(phicnode, 0);
                    for (size_t i = 0; i < jl_array_nrows(values); ++i) {
                        jl_value_t *val = jl_array_ptr_ref(values, i);
                        assert(jl_is_ssavalue(val));
                        size_t upsilon = ((jl_ssavalue_t*)val)->id - 1;
                        assert(jl_is_upsilonnode(jl_array_ptr_ref(stmts, upsilon)));
                        s->locals[jl_source_nslots(s->src) + upsilon] = jl_box_ssavalue(catch_ip + 1);
                    }
                    s->locals[jl_source_nslots(s->src) + catch_ip] = NULL;
                    catch_ip += 1;
                }
                // store current top of exception stack for restore in pop_exception.
            }
            s->locals[jl_source_nslots(s->src) + ip] = jl_box_ulong(jl_excstack_state(ct));
            if (jl_enternode_scope(stmt)) {
                jl_value_t *old_scope = ct->scope; // Identical to __eh.scope
                // GC preserve the old_scope, since it is not rooted in the `jl_handler_t *`
                // and may be removed from jl_current_task by any nested block and then
                // replaced later
                JL_GC_PUSH1(&old_scope);
                jl_value_t *scope = eval_value(jl_enternode_scope(stmt), s);
                ct->scope = scope;
                jl_gc_wb(ct, scope);
                if (!jl_setjmp(__eh.eh_ctx, 0)) {
                    ct->eh = &__eh;
                    eval_body(stmts, s, next_ip, toplevel);
                    jl_unreachable();
                }
                JL_GC_POP();
            }
            else {
                if (!jl_setjmp(__eh.eh_ctx, 0)) {
                    ct->eh = &__eh;
                    eval_body(stmts, s, next_ip, toplevel);
                    jl_unreachable();
                }
            }

            if (s->continue_at) { // means we reached a :leave expression
                jl_eh_restore_state_noexcept(ct, &__eh);
                ip = s->continue_at;
                s->continue_at = 0;
                continue;
            }

Review comment (suggestion):
This comment is now out of date.
While updating it, can you explain in this comment why we don't need to preserve the new scope, since this was clearly confusing when it was originally written and to readers now? Maybe something like this?
```suggestion
                // GC preserve the old_scope, since it is not rooted in the `jl_handler_t *`,
                // and is no longer referenced from jl_current_task.  NOTE that we do not
                // need to preserve the new scope, since the active task will root the new
                // scope, and it will always set a write-barrier to its scope whenever it is
                // switched away from.
```

Code after:
            size_t catch_ip = jl_enternode_catch_dest(stmt);
            if (catch_ip) {
                catch_ip -= 1;
                while (catch_ip < ns) {
                    jl_value_t *phicnode = jl_array_ptr_ref(stmts, catch_ip);
                    if (!jl_is_phicnode(phicnode))
                        break;
                    jl_array_t *values = (jl_array_t*)jl_fieldref_noalloc(phicnode, 0);
                    for (size_t i = 0; i < jl_array_nrows(values); ++i) {
                        jl_value_t *val = jl_array_ptr_ref(values, i);
                        assert(jl_is_ssavalue(val));
                        size_t upsilon = ((jl_ssavalue_t*)val)->id - 1;
                        assert(jl_is_upsilonnode(jl_array_ptr_ref(stmts, upsilon)));
                        s->locals[jl_source_nslots(s->src) + upsilon] = jl_box_ssavalue(catch_ip + 1);
                    }
                    s->locals[jl_source_nslots(s->src) + catch_ip] = NULL;
                    catch_ip += 1;
                }
                // store current top of exception stack for restore in pop_exception.
            }
            s->locals[jl_source_nslots(s->src) + ip] = jl_box_ulong(jl_excstack_state(ct));
            if (jl_enternode_scope(stmt)) {
                jl_value_t *old_scope = ct->scope; // Identical to __eh.scope
                // GC preserve the old_scope, since it is not rooted in the `jl_handler_t *`,
                // the newly entered scope is preserved through the current_task.
                JL_GC_PUSH1(&old_scope);
                ct->scope = eval_value(jl_enternode_scope(stmt), s);
                jl_gc_wb_current_task(ct, ct->scope);
                if (!jl_setjmp(__eh.eh_ctx, 0)) {
                    ct->eh = &__eh;
                    eval_body(stmts, s, next_ip, toplevel);
                    jl_unreachable();
                }
                JL_GC_POP();
            }
            else {
                if (!jl_setjmp(__eh.eh_ctx, 0)) {
                    ct->eh = &__eh;
                    eval_body(stmts, s, next_ip, toplevel);
                    jl_unreachable();
                }
            }

            if (s->continue_at) { // means we reached a :leave expression
                jl_eh_restore_state_noexcept(ct, &__eh);
                ip = s->continue_at;
                s->continue_at = 0;
                continue;
            }
            else { // a real exception
                jl_eh_restore_state(ct, &__eh);