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); }
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); }
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; }
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(); }
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); }
// 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(); }
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); }
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); }
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); }
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 }
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(); }
// 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(); }