示例#1
0
    void ExtensionFinalizer::finalize(STATE) {
      ManagedPhase managed(state);

      NativeMethodEnvironment* env = state->vm()->native_method_environment;
      NativeMethodFrame nmf(env, 0, 0);
      ExceptionPoint ep(env);

      CallFrame* previous_frame = 0;
      CallFrame* call_frame = ALLOCA_CALL_FRAME(0);

      call_frame->previous = NULL;
      call_frame->lexical_scope_ = 0;
      call_frame->dispatch_data = (void*)&nmf;
      call_frame->compiled_code = 0;
      call_frame->flags = CallFrame::cNativeMethod;
      call_frame->top_scope_ = 0;
      call_frame->scope = 0;
      call_frame->arguments = 0;

      env->set_current_call_frame(0);
      env->set_current_native_frame(&nmf);

      // Register the CallFrame, because we might GC below this.
      if(state->vm()->push_call_frame(state, call_frame, previous_frame)) {
        nmf.setup(Qnil, Qnil, Qnil, Qnil);

        PLACE_EXCEPTION_POINT(ep);

        if(unlikely(ep.jumped_to())) {
          logger::warn(
              "finalizer: an exception occurred running a NativeMethod finalizer");
        } else {
          (*finalizer_)(state, object());
        }

        state->vm()->pop_call_frame(state, previous_frame);
        env->set_current_call_frame(0);
        env->set_current_native_frame(0);
      } else {
        logger::warn("finalizer: stack error");
      }
    }
  // Installed by default in BlockEnvironment::execute, it runs the bytecodes
  // for the block in the interpreter.
  //
  // Future code will detect hot blocks and queue them in the JIT, whereby the
  // JIT will install a newly minted machine function into ::execute.
  Object* BlockEnvironment::execute_interpreter(STATE,
                            BlockEnvironment* env, Arguments& args,
                            BlockInvocation& invocation)
  {
    // Don't use env->machine_code() because it might lock and the work should
    // already be done.
    MachineCode* const mcode = env->compiled_code()->machine_code();

    if(!mcode) {
      Exception::internal_error(state, "invalid bytecode method");
      return 0;
    }

#ifdef ENABLE_LLVM
    if(mcode->call_count >= 0) {
      if(mcode->call_count >= state->shared().config.jit_threshold_compile) {
        OnStack<1> os(state, env);

        G(jit)->compile_soon(state, env->compiled_code(),
            invocation.self->direct_class(state), env, true);
      } else {
        mcode->call_count++;
      }
    }
#endif

    StackVariables* scope = ALLOCA_STACKVARIABLES(mcode->number_of_locals);

    Module* mod = invocation.module;
    if(!mod) mod = env->module();

    Object* block = cNil;
    if(VariableScope* vs = env->top_scope()) {
      if(!vs->nil_p()) block = vs->block();
    }

    scope->initialize(invocation.self, block, mod, mcode->number_of_locals);
    scope->set_parent(env->scope());

    if(!GenericArguments::call(state, mcode, scope, args, invocation.flags)) {
      if(state->vm()->thread_state()->raise_reason() == cNone) {
        Exception* exc =
          Exception::make_argument_error(state, mcode->required_args, args.total(),
                                         mcode->name());
        exc->locations(state, Location::from_call_stack(state));
        state->raise_exception(exc);
      }

      return NULL;
    }

    CallFrame* previous_frame = NULL;
    CallFrame* call_frame = ALLOCA_CALL_FRAME(mcode->stack_size);

    call_frame->prepare(mcode->stack_size);

    call_frame->constant_scope_ = invocation.constant_scope;

    call_frame->previous = NULL;
    call_frame->arguments = &args;
    call_frame->dispatch_data = env;
    call_frame->compiled_code = env->compiled_code();
    call_frame->scope = scope;
    call_frame->optional_jit_data = NULL;
    call_frame->top_scope_ = env->top_scope();
    call_frame->flags = invocation.flags | CallFrame::cMultipleScopes
                                    | CallFrame::cBlock;

    if(!state->vm()->push_call_frame(state, call_frame, previous_frame)) {
      return NULL;
    }

    Object* value = NULL;

#ifdef RBX_PROFILER
    if(unlikely(state->vm()->tooling())) {
      Module* mod = scope->module();
      if(SingletonClass* sc = try_as<SingletonClass>(mod)) {
        if(Module* ma = try_as<Module>(sc->singleton())) {
          mod = ma;
        }
      }

      OnStack<2> os(state, env, mod);

      tooling::BlockEntry method(state, env, mod);
      value = (*mcode->run)(state, mcode);
    } else {
      value = (*mcode->run)(state, mcode);
    }
#else
    value = (*mcode->run)(state, mcode);
#endif

    if(!state->vm()->pop_call_frame(state, previous_frame)) {
      return NULL;
    }

    return value;
  }