Beispiel #1
0
fnasso_error fnasso_context_set_cache_name(fnasso_context *ctx, const char* ccache_name)
{
	F_BEGIN();
	if (!ctx) E_RETURN(FNASSO_ERR_NO_CONTEXT_SUPPLIED);

	if (!ccache_name)
	{
		if (ctx->ccache_filename) free(ctx->ccache_filename);
		ctx->ccache_filename = NULL;
		EVENT("Credentials cache filename has been set to OS default");
	}
	else
	{
		if (strlen(ccache_name))
		{
			ctx->ccache_filename = (char *) realloc(ctx->ccache_filename, strlen(ccache_name) + 1);
			strcpy(ctx->ccache_filename, ccache_name);
			EVENT("Credentials cache filename is now (%s)", ctx->ccache_filename);
		}
		else
		{
			E_RETURN(FNASSO_ERR_NO_CCACHE_NAME);
		}
	}
	RETURN(FNASSO_ERR_NONE);
}
Beispiel #2
0
ssod_error ssod_thread_start(ssod_iface *iface)
{
	F_BEGIN();
	int retval;
	ssod_error error;
	if (!iface) E_RETURN(SSOD_ERR_IFACE_NOT_SUPPLIED);
	if (!iface->thread)
	{
		error = ssod_thread_init(iface);
		if (error) E_THROW(error);
	}
	
	if (iface->thread->status == SSOD_THREAD_STATUS_RUNNING) RETURN(SSOD_ERR_NONE);

	iface->thread->status = SSOD_THREAD_STATUS_RUNNING;
	retval = pthread_create(&iface->thread->id, NULL, ssod_network_watcher, iface);
	if (retval)
	{
		iface->thread->status = SSOD_THREAD_STATUS_STOPPED;
		E_RETURN(SSOD_ERR_EXTERNAL, "pthread_create", error_message(retval));
	}

	EVENT("[%s] thread started", iface->name);

	RETURN(SSOD_ERR_NONE);
}
Beispiel #3
0
fnasso_error fnasso_kdc_init(fnasso_context *ctx)
{
	F_BEGIN();
	krb5_error_code kerberos_error;
	krb5_context *context;
	
	if (!ctx->kdc)
	{
		ctx->kdc = (fnasso_kdc*) calloc(1, sizeof(fnasso_kdc));
	}

	if (!ctx->kdc->kctx)
	{
		context = ctx->kdc->kctx = (krb5_context *) malloc(sizeof (krb5_context));

		kerberos_error = krb5_init_context(context);
		if (kerberos_error)
		{
			fnasso_kdc_free(ctx);
			E_RETURN(FNASSO_ERR_EXTERNAL, "krb5_init_context", error_message(kerberos_error));
		}
		DEBUG("krb5_init_context OK");
	}
	else
	{
		context = ctx->kdc->kctx;
		DEBUG("context allready initialized");
	}


	// Setup the right roaming kerberos realm
	if (ctx->roaming_realm)
	{
		EVENT("found kerberos roaming realm (%s), overwriting default realm", ctx->roaming_realm);
		kerberos_error = krb5_set_default_realm(*context, ctx->roaming_realm);
		if (kerberos_error)
		{
			fnasso_kdc_free(ctx);
			E_RETURN(FNASSO_ERR_EXTERNAL, "krb5_set_default_realm", error_message(kerberos_error));
		}
		DEBUG("krb5_set_default_realm OK");
	}
	else
	{
		WARN("default realm not found in context, using default realm from /etc/krb5.conf");
	}

	RETURN(FNASSO_ERR_NONE);
}
/**
** Called to perform WordFinder creation and text extraction on a PDF document
**
** @param pdDoc IN The PDDoc object on which to perform text extraction.
** @param startPg IN The page to start text extraction.
** @param endPg IN The page to end text extraction (inclusive).
** @param toUnicode IN Whether to extract text to Unicode encoding.
** @param pConfig IN Pointer to a WordFinder Configuration Record.
** @param pOutput IN/OUT Pointer to an output FILE stream to which the extracted 
**	text will be written.
** @return true to indicate text extraction operation a success, false otherwise.
*/
bool ExtractText(PDDoc pdDoc, ASInt32 startPg, ASInt32 endPg, 
				 ASBool toUnicode, PDWordFinderConfig pConfig, FILE* pOutput)
{
	if (startPg < 0 || endPg <0 || startPg > endPg || endPg > PDDocGetNumPages(pdDoc) - 1)
	{
		AVAlertNote("Exceeding starting or ending page number limit of current document."); 
		return false;
	}

	PDWordFinder pdWordFinder = NULL;

DURING	
	pdWordFinder = PDDocCreateWordFinderEx(pdDoc, WF_LATEST_VERSION, toUnicode, pConfig);
	
	if (toUnicode) fprintf(pOutput, "%c%c", 0xfe, 0xff);

	for (int i = startPg; i <= endPg; i++)
		PDWordFinderEnumWords(pdWordFinder, i, ASCallbackCreateProto(PDWordProc, &WordEnumProc), pOutput);

	PDWordFinderDestroy(pdWordFinder);
	E_RETURN(true);
HANDLER
	char buf[256], errmsg[256];
	sprintf(buf, "[ExtractText()]Error %d: %s",  ErrGetCode(ERRORCODE), ASGetErrorString(ERRORCODE, errmsg, sizeof(errmsg)));
	AVAlertNote(buf);
	if (pdWordFinder) PDWordFinderDestroy(pdWordFinder);
	if( pOutput) fclose(pOutput);
	return false;
END_HANDLER

return true;
}
Beispiel #5
0
value_t read_file_to_blob(runtime_t *runtime, string_t *filename) {
  FILE *handle = fopen(filename->chars, "r");
  if (handle == NULL)
    return new_system_error_condition(seFileNotFound);
  E_BEGIN_TRY_FINALLY();
    E_RETURN(read_handle_to_blob(runtime, handle));
  E_FINALLY();
    fclose(handle);
  E_END_TRY_FINALLY();
}
Beispiel #6
0
ssod_error ssod_thread_stop(ssod_iface *iface)
{
	F_BEGIN();
	int retval;
	if (!iface) E_RETURN(SSOD_ERR_IFACE_NOT_SUPPLIED);
	if (!iface->thread) ssod_thread_init(iface);
	//if (iface->thread->status) RETURN(SSOD_ERR_NONE);
	iface->thread->status = SSOD_THREAD_STATUS_MUST_EXIT;

	RETURN(SSOD_ERR_NONE);
}
Beispiel #7
0
// Returns the code that implements the given method object.
static value_t compile_method(runtime_t *runtime, value_t method) {
    value_t method_ast = get_method_syntax(method);
    value_t fragment = get_method_module_fragment(method);
    assembler_t assm;
    TRY(assembler_init(&assm, runtime, fragment, scope_get_bottom()));
    E_BEGIN_TRY_FINALLY();
    E_TRY_DEF(code, compile_method_body(&assm, method_ast));
    E_RETURN(code);
    E_FINALLY();
    assembler_dispose(&assm);
    E_END_TRY_FINALLY();
}
Beispiel #8
0
fnasso_error fnasso_context_set_roaming_realm(fnasso_context *ctx, const char* roaming_realm)
{
	F_BEGIN();
	krb5_error_code kerberos_error;
	if (!ctx) E_RETURN(FNASSO_ERR_NO_CONTEXT_SUPPLIED);

	if (!roaming_realm)
	{
		if (ctx->roaming_realm) free(ctx->roaming_realm);
		ctx->roaming_realm = NULL;
		EVENT("roaming realm restored to default realm in /etc/krb5.conf");
	}
	else
	{
		if (strlen(roaming_realm))
		{
			ctx->roaming_realm = (char *) realloc(ctx->roaming_realm, strlen(roaming_realm) + 1);
			strcpy(ctx->roaming_realm, roaming_realm);
			EVENT("roaming realm is now (%s)", ctx->roaming_realm);
		}
		else
		{
			E_RETURN(FNASSO_ERR_NO_ROAMING_REALM);
		}
	}

	if (ctx->kdc && ctx->kdc->kctx)
	{
		EVENT("updating current KDC default realm");
		kerberos_error = krb5_set_default_realm(*ctx->kdc->kctx, ctx->roaming_realm);
		if (kerberos_error)
		{
			fnasso_kdc_free(ctx);
			E_RETURN(FNASSO_ERR_EXTERNAL, "krb5_set_default_realm", error_message(kerberos_error));
		}
		DEBUG("krb5_set_default_realm OK");
	}

	RETURN(FNASSO_ERR_NONE);
}
Beispiel #9
0
ssod_error ssod_thread_init(ssod_iface *iface)
{
	F_BEGIN();
	ssod_error error;
	if (!iface) E_RETURN(SSOD_ERR_IFACE_NOT_SUPPLIED);

	error = ssod_thread_free(iface);
	if (error) E_THROW(error);

	iface->thread = (ssod_thread*) malloc(sizeof (ssod_thread));
	iface->thread->status = SSOD_THREAD_STATUS_STOPPED;

	RETURN(SSOD_ERR_NONE);
}
Beispiel #10
0
ssod_error ssod_thread_free(ssod_iface *iface)
{
	F_BEGIN();
	if (!iface) E_RETURN(SSOD_ERR_IFACE_NOT_SUPPLIED);

	if (iface->thread)
	{
		ssod_thread_stop(iface);
		free(iface->thread);
		iface->thread = NULL;
	}

	RETURN(SSOD_ERR_NONE);
}
Beispiel #11
0
value_t compile_method_ast_to_method(runtime_t *runtime, value_t method_ast,
    value_t fragment) {
  reusable_scratch_memory_t scratch;
  reusable_scratch_memory_init(&scratch);
  TRY_FINALLY {
    E_TRY_DEF(signature, build_method_signature(runtime, fragment, &scratch,
        get_method_ast_signature(method_ast)));
    E_TRY_DEF(method, new_heap_method(runtime, afMutable, signature, method_ast,
        nothing(), fragment, new_flag_set(kFlagSetAllOff)));
    E_RETURN(method);
  } FINALLY {
    reusable_scratch_memory_dispose(&scratch);
  } YRT
}
Beispiel #12
0
value_t run_code_block(safe_value_t s_ambience, safe_value_t code) {
    runtime_t *runtime = get_ambience_runtime(deref(s_ambience));
    CREATE_SAFE_VALUE_POOL(runtime, 4, pool);
    E_BEGIN_TRY_FINALLY();
    // Build a stack to run the code on.
    E_S_TRY_DEF(s_stack, protect(pool, new_heap_stack(runtime, 1024)));
    {
        frame_t frame = open_stack(deref(s_stack));
        // Set up the initial frame.
        size_t frame_size = get_code_block_high_water_mark(deref(code));
        E_TRY(push_stack_frame(runtime, deref(s_stack), &frame, frame_size,
                               ROOT(runtime, empty_array)));
        frame_set_code_block(&frame, deref(code));
        close_frame(&frame);
    }
    // Run until completion.
    E_RETURN(run_stack_until_signal(s_ambience, s_stack));
    E_FINALLY();
    DISPOSE_SAFE_VALUE_POOL(pool);
    E_END_TRY_FINALLY();
}
Beispiel #13
0
// Runs the given stack within the given ambience until a condition is
// encountered or evaluation completes. This function also bails on and leaves
// it to the surrounding code to report error messages.
static value_t run_stack_pushing_signals(value_t ambience, value_t stack) {
    CHECK_FAMILY(ofAmbience, ambience);
    CHECK_FAMILY(ofStack, stack);
    runtime_t *runtime = get_ambience_runtime(ambience);
    frame_t frame = open_stack(stack);
    code_cache_t cache;
    code_cache_refresh(&cache, &frame);
    E_BEGIN_TRY_FINALLY();
    while (true) {
        opcode_t opcode = (opcode_t) read_short(&cache, &frame, 0);
        TOPIC_INFO(Interpreter, "Opcode: %s (%i)", get_opcode_name(opcode),
                   opcode_counter++);
        IF_EXPENSIVE_CHECKS_ENABLED(MAYBE_INTERRUPT());
        switch (opcode) {
        case ocPush: {
            value_t value = read_value(&cache, &frame, 1);
            frame_push_value(&frame, value);
            frame.pc += kPushOperationSize;
            break;
        }
        case ocPop: {
            size_t count = read_short(&cache, &frame, 1);
            for (size_t i = 0; i < count; i++)
                frame_pop_value(&frame);
            frame.pc += kPopOperationSize;
            break;
        }
        case ocCheckStackHeight: {
            size_t expected = read_short(&cache, &frame, 1);
            size_t height = frame.stack_pointer - frame.frame_pointer;
            CHECK_EQ("stack height", expected, height);
            frame.pc += kCheckStackHeightOperationSize;
            break;
        }
        case ocNewArray: {
            size_t length = read_short(&cache, &frame, 1);
            E_TRY_DEF(array, new_heap_array(runtime, length));
            for (size_t i = 0; i < length; i++) {
                value_t element = frame_pop_value(&frame);
                set_array_at(array, length - i - 1, element);
            }
            frame_push_value(&frame, array);
            frame.pc += kNewArrayOperationSize;
            break;
        }
        case ocInvoke: {
            // Look up the method in the method space.
            value_t tags = read_value(&cache, &frame, 1);
            CHECK_FAMILY(ofCallTags, tags);
            value_t fragment = read_value(&cache, &frame, 2);
            CHECK_FAMILY(ofModuleFragment, fragment);
            value_t helper = read_value(&cache, &frame, 3);
            CHECK_FAMILY(ofSignatureMap, helper);
            value_t arg_map;
            value_t method = lookup_method_full(ambience, fragment, tags, &frame,
                                                helper, &arg_map);
            if (in_condition_cause(ccLookupError, method)) {
                log_lookup_error(method, tags, &frame);
                E_RETURN(method);
            }
            // The lookup may have failed with a different condition. Check for that.
            E_TRY(method);
            E_TRY_DEF(code_block, ensure_method_code(runtime, method));
            // We should now have done everything that can fail so we advance the
            // pc over this instruction. In reality we haven't, the frame push op
            // below can fail so we should really push the next frame before
            // storing the pc for this one. Laters.
            frame.pc += kInvokeOperationSize;
            // Push a new activation.
            E_TRY(push_stack_frame(runtime, stack, &frame,
                                   get_code_block_high_water_mark(code_block), arg_map));
            frame_set_code_block(&frame, code_block);
            code_cache_refresh(&cache, &frame);
            break;
        }
        case ocSignalContinue:
        case ocSignalEscape: {
            // Look up the method in the method space.
            value_t tags = read_value(&cache, &frame, 1);
            CHECK_FAMILY(ofCallTags, tags);
            frame.pc += kSignalEscapeOperationSize;
            value_t arg_map = whatever();
            value_t handler = whatever();
            value_t method = lookup_signal_handler_method(ambience, tags, &frame,
                             &handler, &arg_map);
            bool is_escape = (opcode == ocSignalEscape);
            if (in_condition_cause(ccLookupError, method)) {
                if (is_escape) {
                    // There was no handler for this so we have to escape out of the
                    // interpreter altogether. Push the signal frame onto the stack to
                    // record the state of it for the enclosing code.
                    E_TRY(push_stack_frame(runtime, stack, &frame, 1, nothing()));
                    // The stack tracing code expects all frames to have a valid code block
                    // object. The rest makes less of a difference.
                    frame_set_code_block(&frame, ROOT(runtime, empty_code_block));
                    E_RETURN(new_signal_condition(is_escape));
                } else {
                    // There was no handler but this is not an escape so we skip over
                    // the post-handler goto to the default block.
                    CHECK_EQ("signal not followed by goto", ocGoto,
                             read_short(&cache, &frame, 0));
                    frame.pc += kGotoOperationSize;
                }
            } else {
                // We found a method. Invoke it.
                E_TRY(method);
                E_TRY_DEF(code_block, ensure_method_code(runtime, method));
                E_TRY(push_stack_frame(runtime, stack, &frame,
                                       get_code_block_high_water_mark(code_block), arg_map));
                frame_set_code_block(&frame, code_block);
                CHECK_TRUE("subject not null", is_null(frame_get_argument(&frame, 0)));
                frame_set_argument(&frame, 0, handler);
                code_cache_refresh(&cache, &frame);
            }
            break;
        }
        case ocGoto: {
            size_t delta = read_short(&cache, &frame, 1);
            frame.pc += delta;
            break;
        }
        case ocDelegateToLambda:
        case ocDelegateToBlock: {
            // This op only appears in the lambda and block delegator methods.
            // They should never be executed because the delegation happens during
            // method lookup. If we hit here something's likely wrong with the
            // lookup process.
            UNREACHABLE("delegate to lambda");
            return new_condition(ccWat);
        }
        case ocBuiltin: {
            value_t wrapper = read_value(&cache, &frame, 1);
            builtin_method_t impl = (builtin_method_t) get_void_p_value(wrapper);
            builtin_arguments_t args;
            builtin_arguments_init(&args, runtime, &frame);
            E_TRY_DEF(result, impl(&args));
            frame_push_value(&frame, result);
            frame.pc += kBuiltinOperationSize;
            break;
        }
        case ocBuiltinMaybeEscape: {
            value_t wrapper = read_value(&cache, &frame, 1);
            builtin_method_t impl = (builtin_method_t) get_void_p_value(wrapper);
            builtin_arguments_t args;
            builtin_arguments_init(&args, runtime, &frame);
            value_t result = impl(&args);
            if (in_condition_cause(ccSignal, result)) {
                // The builtin failed. Find the appropriate signal handler and call
                // it. The invocation record is at the top of the stack.
                value_t tags = frame_pop_value(&frame);
                CHECK_FAMILY(ofCallTags, tags);
                value_t arg_map = whatever();
                value_t handler = whatever();
                value_t method = lookup_signal_handler_method(ambience, tags, &frame,
                                 &handler, &arg_map);
                if (in_condition_cause(ccLookupError, method)) {
                    // Push the record back onto the stack to it's available to back
                    // tracing.
                    frame_push_value(&frame, tags);
                    frame.pc += kBuiltinMaybeEscapeOperationSize;
                    // There was no handler for this so we have to escape out of the
                    // interpreter altogether. Push the signal frame onto the stack to
                    // record the state of it for the enclosing code.
                    E_TRY(push_stack_frame(runtime, stack, &frame, 1, nothing()));
                    // The stack tracing code expects all frames to have a valid code block
                    // object. The rest makes less of a difference.
                    frame_set_code_block(&frame, ROOT(runtime, empty_code_block));
                    E_RETURN(new_signal_condition(true));
                }
                // Either found a signal or encountered a different condition.
                E_TRY(method);
                // Skip forward to the point we want the signal to return to, the
                // leave-or-fire-barrier op that will do the leaving.
                size_t dest_offset = read_short(&cache, &frame, 2);
                frame.pc += dest_offset;
                // Run the handler.
                E_TRY_DEF(code_block, ensure_method_code(runtime, method));
                E_TRY(push_stack_frame(runtime, stack, &frame,
                                       get_code_block_high_water_mark(code_block), arg_map));
                frame_set_code_block(&frame, code_block);
                CHECK_TRUE("subject not null", is_null(frame_get_argument(&frame, 0)));
                frame_set_argument(&frame, 0, handler);
                code_cache_refresh(&cache, &frame);
            } else {
                // The builtin didn't cause a condition so we can just keep going.
                E_TRY(result);
                frame_push_value(&frame, result);
                frame.pc += kBuiltinMaybeEscapeOperationSize;
            }
            break;
        }
        case ocReturn: {
            value_t result = frame_pop_value(&frame);
            frame_pop_within_stack_piece(&frame);
            code_cache_refresh(&cache, &frame);
            frame_push_value(&frame, result);
            break;
        }
        case ocStackBottom: {
            value_t result = frame_pop_value(&frame);
            validate_stack_on_normal_exit(&frame);
            E_RETURN(result);
        }
        case ocStackPieceBottom: {
            value_t top_piece = frame.stack_piece;
            value_t result = frame_pop_value(&frame);
            value_t next_piece = get_stack_piece_previous(top_piece);
            set_stack_top_piece(stack, next_piece);
            frame = open_stack(stack);
            code_cache_refresh(&cache, &frame);
            frame_push_value(&frame, result);
            break;
        }
        case ocSlap: {
            value_t value = frame_pop_value(&frame);
            size_t argc = read_short(&cache, &frame, 1);
            for (size_t i = 0; i < argc; i++)
                frame_pop_value(&frame);
            frame_push_value(&frame, value);
            frame.pc += kSlapOperationSize;
            break;
        }
        case ocNewReference: {
            // Create the reference first so that if it fails we haven't clobbered
            // the stack yet.
            E_TRY_DEF(ref, new_heap_reference(runtime, nothing()));
            value_t value = frame_pop_value(&frame);
            set_reference_value(ref, value);
            frame_push_value(&frame, ref);
            frame.pc += kNewReferenceOperationSize;
            break;
        }
        case ocSetReference: {
            value_t ref = frame_pop_value(&frame);
            CHECK_FAMILY(ofReference, ref);
            value_t value = frame_peek_value(&frame, 0);
            set_reference_value(ref, value);
            frame.pc += kSetReferenceOperationSize;
            break;
        }
        case ocGetReference: {
            value_t ref = frame_pop_value(&frame);
            CHECK_FAMILY(ofReference, ref);
            value_t value = get_reference_value(ref);
            frame_push_value(&frame, value);
            frame.pc += kGetReferenceOperationSize;
            break;
        }
        case ocLoadLocal: {
            size_t index = read_short(&cache, &frame, 1);
            value_t value = frame_get_local(&frame, index);
            frame_push_value(&frame, value);
            frame.pc += kLoadLocalOperationSize;
            break;
        }
        case ocLoadGlobal: {
            value_t ident = read_value(&cache, &frame, 1);
            CHECK_FAMILY(ofIdentifier, ident);
            value_t fragment = read_value(&cache, &frame, 2);
            CHECK_FAMILY(ofModuleFragment, fragment);
            value_t module = get_module_fragment_module(fragment);
            E_TRY_DEF(value, module_lookup_identifier(runtime, module,
                      get_identifier_stage(ident), get_identifier_path(ident)));
            frame_push_value(&frame, value);
            frame.pc += kLoadGlobalOperationSize;
            break;
        }
        case ocLoadArgument: {
            size_t param_index = read_short(&cache, &frame, 1);
            value_t value = frame_get_argument(&frame, param_index);
            frame_push_value(&frame, value);
            frame.pc += kLoadArgumentOperationSize;
            break;
        }
        case ocLoadRefractedArgument: {
            size_t param_index = read_short(&cache, &frame, 1);
            size_t block_depth = read_short(&cache, &frame, 2);
            value_t subject = frame_get_argument(&frame, 0);
            frame_t home = frame_empty();
            get_refractor_refracted_frame(subject, block_depth, &home);
            value_t value = frame_get_argument(&home, param_index);
            frame_push_value(&frame, value);
            frame.pc += kLoadRefractedArgumentOperationSize;
            break;
        }
        case ocLoadRefractedLocal: {
            size_t index = read_short(&cache, &frame, 1);
            size_t block_depth = read_short(&cache, &frame, 2);
            value_t subject = frame_get_argument(&frame, 0);
            frame_t home = frame_empty();
            get_refractor_refracted_frame(subject, block_depth, &home);
            value_t value = frame_get_local(&home, index);
            frame_push_value(&frame, value);
            frame.pc += kLoadRefractedLocalOperationSize;
            break;
        }
        case ocLoadLambdaCapture: {
            size_t index = read_short(&cache, &frame, 1);
            value_t subject = frame_get_argument(&frame, 0);
            CHECK_FAMILY(ofLambda, subject);
            value_t value = get_lambda_capture(subject, index);
            frame_push_value(&frame, value);
            frame.pc += kLoadLambdaCaptureOperationSize;
            break;
        }
        case ocLoadRefractedCapture: {
            size_t index = read_short(&cache, &frame, 1);
            size_t block_depth = read_short(&cache, &frame, 2);
            value_t subject = frame_get_argument(&frame, 0);
            frame_t home = frame_empty();
            get_refractor_refracted_frame(subject, block_depth, &home);
            value_t lambda = frame_get_argument(&home, 0);
            CHECK_FAMILY(ofLambda, lambda);
            value_t value = get_lambda_capture(lambda, index);
            frame_push_value(&frame, value);
            frame.pc += kLoadRefractedLocalOperationSize;
            break;
        }
        case ocLambda: {
            value_t space = read_value(&cache, &frame, 1);
            CHECK_FAMILY(ofMethodspace, space);
            size_t capture_count = read_short(&cache, &frame, 2);
            value_t captures;
            E_TRY_DEF(lambda, new_heap_lambda(runtime, space, nothing()));
            if (capture_count == 0) {
                captures = ROOT(runtime, empty_array);
                frame.pc += kLambdaOperationSize;
            } else {
                E_TRY_SET(captures, new_heap_array(runtime, capture_count));
                // The pc gets incremented here because it is after we've done all
                // the allocation but before anything has been popped off the stack.
                // This way all the above is idempotent, and the below is guaranteed
                // to succeed.
                frame.pc += kLambdaOperationSize;
                for (size_t i = 0; i < capture_count; i++)
                    set_array_at(captures, i, frame_pop_value(&frame));
            }
            set_lambda_captures(lambda, captures);
            frame_push_value(&frame, lambda);
            break;
        }
        case ocCreateBlock: {
            value_t space = read_value(&cache, &frame, 1);
            CHECK_FAMILY(ofMethodspace, space);
            // Create the block object.
            E_TRY_DEF(block, new_heap_block(runtime, nothing()));
            // Create the stack section that describes the block.
            value_t section = frame_alloc_derived_object(&frame, get_genus_descriptor(dgBlockSection));
            set_barrier_state_payload(section, block);
            refraction_point_init(section, &frame);
            set_block_section_methodspace(section, space);
            set_block_section(block, section);
            value_validate(block);
            value_validate(section);
            // Push the block object.
            frame_push_value(&frame, block);
            frame.pc += kCreateBlockOperationSize;
            break;
        }
        case ocCreateEnsurer: {
            value_t code_block = read_value(&cache, &frame, 1);
            value_t section = frame_alloc_derived_object(&frame,
                              get_genus_descriptor(dgEnsureSection));
            set_barrier_state_payload(section, code_block);
            refraction_point_init(section, &frame);
            value_validate(section);
            frame_push_value(&frame, section);
            frame.pc += kCreateEnsurerOperationSize;
            break;
        }
        case ocCallEnsurer: {
            value_t value = frame_pop_value(&frame);
            value_t shard = frame_pop_value(&frame);
            frame_push_value(&frame, value);
            frame_push_value(&frame, shard);
            CHECK_GENUS(dgEnsureSection, shard);
            value_t code_block = get_barrier_state_payload(shard);
            CHECK_FAMILY(ofCodeBlock, code_block);
            // Unregister the barrier before calling it, otherwise if we leave
            // by escaping we'll end up calling it over again.
            barrier_state_unregister(shard, stack);
            frame.pc += kCallEnsurerOperationSize;
            value_t argmap = ROOT(runtime, array_of_zero);
            push_stack_frame(runtime, stack, &frame,
                             get_code_block_high_water_mark(code_block), argmap);
            frame_set_code_block(&frame, code_block);
            code_cache_refresh(&cache, &frame);
            break;
        }
        case ocDisposeEnsurer: {
            // Discard the result of the ensure block. If an ensure blocks needs
            // to return a useful value it can do it via an escape.
            frame_pop_value(&frame);
            value_t shard = frame_pop_value(&frame);
            CHECK_GENUS(dgEnsureSection, shard);
            value_t value = frame_pop_value(&frame);
            frame_destroy_derived_object(&frame, get_genus_descriptor(dgEnsureSection));
            frame_push_value(&frame, value);
            frame.pc += kDisposeEnsurerOperationSize;
            break;
        }
        case ocInstallSignalHandler: {
            value_t space = read_value(&cache, &frame, 1);
            CHECK_FAMILY(ofMethodspace, space);
            size_t dest_offset = read_short(&cache, &frame, 2);
            // Allocate the derived object that's going to hold the signal handler
            // state.
            value_t section = frame_alloc_derived_object(&frame,
                              get_genus_descriptor(dgSignalHandlerSection));
            // Initialize the handler.
            set_barrier_state_payload(section, space);
            refraction_point_init(section, &frame);
            // Bring the frame state to the point we'll want to escape to (modulo
            // the destination offset).
            frame_push_value(&frame, section);
            frame.pc += kInstallSignalHandlerOperationSize;
            // Finally capture the escape state.
            capture_escape_state(section, &frame, dest_offset);
            value_validate(section);
            break;
        }
        case ocUninstallSignalHandler: {
            // The result has been left at the top of the stack.
            value_t value = frame_pop_value(&frame);
            value_t section = frame_pop_value(&frame);
            CHECK_GENUS(dgSignalHandlerSection, section);
            barrier_state_unregister(section, stack);
            frame_destroy_derived_object(&frame, get_genus_descriptor(dgSignalHandlerSection));
            frame_push_value(&frame, value);
            frame.pc += kUninstallSignalHandlerOperationSize;
            break;
        }
        case ocCreateEscape: {
            size_t dest_offset = read_short(&cache, &frame, 1);
            // Create an initially empty escape object.
            E_TRY_DEF(escape, new_heap_escape(runtime, nothing()));
            // Allocate the escape section on the stack, hooking the barrier into
            // the barrier chain.
            value_t section = frame_alloc_derived_object(&frame, get_genus_descriptor(dgEscapeSection));
            // Point the state and object to each other.
            set_barrier_state_payload(section, escape);
            set_escape_section(escape, section);
            // Get execution ready for the next operation.
            frame_push_value(&frame, escape);
            frame.pc += kCreateEscapeOperationSize;
            // This is the execution state the escape will escape to (modulo the
            // destination offset) so this is what we want to capture.
            capture_escape_state(section, &frame,
                                 dest_offset);
            break;
        }
        case ocLeaveOrFireBarrier: {
            size_t argc = read_short(&cache, &frame, 1);
            // At this point the handler has been set as the subject of the call
            // to the handler method. Above the arguments are also two scratch
            // stack entries.
            value_t handler = frame_peek_value(&frame, argc + 2);
            CHECK_GENUS(dgSignalHandlerSection, handler);
            if (maybe_fire_next_barrier(&cache, &frame, runtime, stack, handler)) {
                // Pop the scratch entries off.
                frame_pop_value(&frame);
                frame_pop_value(&frame);
                // Pop the value off.
                value_t value = frame_pop_value(&frame);
                // Escape to the handler's home.
                restore_escape_state(&frame, stack, handler);
                code_cache_refresh(&cache, &frame);
                // Push the value back on, now in the handler's home frame.
                frame_push_value(&frame, value);
            } else {
                // If a barrier was fired we'll want to let the interpreter loop
                // around again so just break without touching .pc.
            }
            break;
        }
        case ocFireEscapeOrBarrier: {
            value_t escape = frame_get_argument(&frame, 0);
            CHECK_FAMILY(ofEscape, escape);
            value_t section = get_escape_section(escape);
            // Fire the next barrier or, if there are no more barriers, apply the
            // escape.
            if (maybe_fire_next_barrier(&cache, &frame, runtime, stack, section)) {
                value_t value = frame_get_argument(&frame, 2);
                restore_escape_state(&frame, stack, section);
                code_cache_refresh(&cache, &frame);
                frame_push_value(&frame, value);
            } else {
                // If a barrier was fired we'll want to let the interpreter loop
                // around again so just break without touching .pc.
            }
            break;
        }
        case ocDisposeEscape: {
            value_t value = frame_pop_value(&frame);
            value_t escape = frame_pop_value(&frame);
            CHECK_FAMILY(ofEscape, escape);
            value_t section = get_escape_section(escape);
            value_validate(section);
            barrier_state_unregister(section, stack);
            on_escape_section_exit(section);
            frame_destroy_derived_object(&frame, get_genus_descriptor(dgEscapeSection));
            frame_push_value(&frame, value);
            frame.pc += kDisposeEscapeOperationSize;
            break;
        }
        case ocDisposeBlock: {
            value_t value = frame_pop_value(&frame);
            value_t block = frame_pop_value(&frame);
            CHECK_FAMILY(ofBlock, block);
            value_t section = get_block_section(block);
            barrier_state_unregister(section, stack);
            on_block_section_exit(section);
            frame_destroy_derived_object(&frame, get_genus_descriptor(dgBlockSection));
            frame_push_value(&frame, value);
            frame.pc += kDisposeBlockOperationSize;
            break;
        }
        default:
            ERROR("Unexpected opcode %i", opcode);
            UNREACHABLE("unexpected opcode");
            break;
        }
    }
    E_FINALLY();
    close_frame(&frame);
    E_END_TRY_FINALLY();
}