Exemple #1
0
  MachineCode* CompiledCode::internalize(STATE, GCToken gct,
                                        const char** reason, int* ip)
  {
    MachineCode* mcode = machine_code_;

    atomic::memory_barrier();

    if(mcode) return mcode;

    CompiledCode* self = this;
    OnStack<1> os(state, self);

    self->hard_lock(state, gct);

    mcode = self->machine_code_;
    if(!mcode) {
      {
        BytecodeVerification bv(self);
        if(!bv.verify(state)) {
          if(reason) *reason = bv.failure_reason();
          if(ip) *ip = bv.failure_ip();
          std::cerr << "Error validating bytecode: " << bv.failure_reason() << "\n";
          return 0;
        }
      }

      mcode = new MachineCode(state, self);

      if(self->resolve_primitive(state)) {
        mcode->fallback = execute;
      } else {
        mcode->setup_argument_handler();
      }

      // We need to have an explicit memory barrier here, because we need to
      // be sure that mcode is completely initialized before it's set.
      // Otherwise another thread might see a partially initialized
      // MachineCode.
      atomic::write(&self->machine_code_, mcode);

      set_executor(mcode->fallback);
    }

    self->hard_unlock(state, gct);
    return mcode;
  }
  MachineCode* CompiledCode::internalize(STATE) {
    timer::StopWatch<timer::microseconds> timer(
        state->vm()->metrics().machine.bytecode_internalizer_us);

    atomic::memory_barrier();

    MachineCode* mcode = machine_code();

    if(mcode) return mcode;

    {
      BytecodeVerifier bytecode_verifier(this);
      bytecode_verifier.verify(state);
    }

    mcode = new MachineCode(state, this);

    if(resolve_primitive(state)) {
      mcode->fallback = execute;
    } else {
      mcode->setup_argument_handler();
    }

    /* There is a race here because another Thread may have run this
     * CompiledCode instance and internalized it. We attempt to store our
     * version assuming that we are the only ones to do so and throw away our
     * work if someone else has beat us to it.
     */
    MachineCode** mcode_ptr = &_machine_code_;
    if(atomic::compare_and_swap(reinterpret_cast<void**>(mcode_ptr), 0, mcode)) {
      set_executor(mcode->fallback);
      return mcode;
    } else {
      return machine_code();
    }
  }