Example #1
0
LeaseHolder::LeaseHolder(const Func* func, TransKind kind, bool isWorker)
  : m_func{RuntimeOption::EvalJitConcurrently > 0 ? func : nullptr}
{
  assertx(func || RuntimeOption::EvalJitConcurrently == 0);
  auto const level = m_func ? lockLevel(kind) : LockLevel::Global;

  if (level == LockLevel::Func && !threadCanAcquireConcurrent) return;

  if (level == LockLevel::Global && !s_globalLease.amOwner()) {
    auto const blocking = RuntimeOption::EvalJitRequireWriteLease &&
      RuntimeOption::EvalJitConcurrently == 0;
    if (!(m_acquiredGlobal = s_globalLease.acquire(blocking))) return;
  }

  SCOPE_EXIT { if (m_level == LockLevel::None) dropLocks(); };

  if (level == LockLevel::Kind && !acquireKind(kind)) return;

  if (m_func) {
    auto const funcId = m_func->getFuncId();
    s_funcOwners.ensureSize(funcId + 1);
    auto& owner = s_funcOwners[funcId];
    auto oldOwner = owner.load(std::memory_order_relaxed);
    auto const self = Treadmill::threadIdx();

    if (oldOwner == self) {
      // We already have the lock on this Func.
    } else if (oldOwner != Treadmill::kInvalidThreadIdx) {
      // Already owned by another thread.
      return;
    } else {
      // Unowned. Try to grab it. Only non-worker threads with LockLevel::Func
      // count towards the Eval.JitThreads limit.
      if (!isWorker && level == LockLevel::Func) {
        auto threads = s_jittingThreads.load(std::memory_order_relaxed);
        if (threads >= RuntimeOption::EvalJitThreads) return;

        threads = s_jittingThreads.fetch_add(1, std::memory_order_relaxed);
        m_acquiredThread = true;
        if (threads >= RuntimeOption::EvalJitThreads) return;
      }

      assertx(oldOwner == Treadmill::kInvalidThreadIdx);
      if (!owner.compare_exchange_strong(oldOwner, self,
                                         std::memory_order_acq_rel)) {
        return;
      }
      m_acquiredFunc = true;
    }
  }

  // If we made it this far, we acquired all the locks we need to translate.
  m_level = level;
}
Example #2
0
LeaseHolder::LeaseHolder(Lease& l, const Func* func, TransKind kind)
  : m_lease(l)
  , m_func{RuntimeOption::EvalJitConcurrently > 0 ? func : nullptr}
{
  auto const need_global = m_func == nullptr || NeedGlobal(kind);

  if (!need_global && !threadCanAcquireConcurrent) return;

  if (need_global && !m_lease.amOwner()) {
    auto const blocking = RuntimeOption::EvalJitRequireWriteLease &&
      RuntimeOption::EvalJitConcurrently == 0;
    if (!(m_acquired = m_lease.acquire(blocking))) return;
  }

  SCOPE_EXIT { if (!m_canTranslate) dropLocks(); };

  if (m_func) {
    auto const funcId = m_func->getFuncId();
    s_funcOwners.ensureSize(funcId + 1);
    auto& owner = s_funcOwners[funcId];
    auto oldOwner = owner.load(std::memory_order_acquire);
    auto const self = Treadmill::threadIdx();

    if (oldOwner == self) {
      // We already have the lock on this Func.
    } else if (oldOwner != Treadmill::kInvalidThreadIdx) {
      // Already owned by another thread.
      return;
    } else {
      // Unowned. Try to grab it. Threads with the global write lease don't
      // count towards Eval.JitThreads.
      if (!need_global) {
        auto threads = s_jittingThreads.load(std::memory_order_relaxed);
        if (threads >= RuntimeOption::EvalJitThreads) return;

        threads = s_jittingThreads.fetch_add(1, std::memory_order_relaxed);
        m_acquiredThread = true;
        if (threads >= RuntimeOption::EvalJitThreads) return;
      }

      if (!owner.compare_exchange_strong(oldOwner, self,
                                         std::memory_order_relaxed)) {
        return;
      }
      m_acquiredFunc = true;
    }
  }

  // If we made it this far, we acquired all the locks we need to translate.
  m_canTranslate = true;
}
JSValuePtr UserObjectImp::callAsFunction(ExecState *exec, JSObject *thisObj, const ArgList &args)
{
    JSValuePtr result = jsUndefined();
    JSUserObject* jsThisObj = KJSValueToJSObject(thisObj, exec);
    if (jsThisObj) {
        CFIndex argCount = args.size();
        CFArrayCallBacks arrayCallBacks;
        JSTypeGetCFArrayCallBacks(&arrayCallBacks);
        CFMutableArrayRef jsArgs = CFArrayCreateMutable(0, 0, &arrayCallBacks);
        if (jsArgs) {
            for (CFIndex i = 0; i < argCount; i++) {
                JSUserObject* jsArg = KJSValueToJSObject(args.at(exec, i), exec);
                CFArrayAppendValue(jsArgs, (void*)jsArg);
                jsArg->Release();
            }
        }

        JSUserObject* jsResult;
        {   // scope
            JSLock::DropAllLocks dropLocks(exec);

            // getCallData should have guarded against a NULL fJSUserObject.
            assert(fJSUserObject);
            jsResult = fJSUserObject->CallFunction(jsThisObj, jsArgs);
        }

        if (jsResult) {
            result = JSObjectKJSValue(jsResult);
            jsResult->Release();
        }

        ReleaseCFType(jsArgs);
        jsThisObj->Release();
    }
    return result;
}
Example #4
0
LeaseHolder::~LeaseHolder() {
  dropLocks();
}