Beispiel #1
0
void CallLinkStatus::dump(PrintStream& out) const
{
    if (!isSet()) {
        out.print("Not Set");
        return;
    }
    
    CommaPrinter comma;
    
    if (m_isProved)
        out.print(comma, "Statically Proved");
    
    if (m_couldTakeSlowPath)
        out.print(comma, "Could Take Slow Path");
    
    if (m_callTarget)
        out.print(comma, "Known target: ", m_callTarget);
    
    if (m_executable) {
        out.print(comma, "Executable/CallHash: ", RawPointer(m_executable));
        if (!isCompilationThread())
            out.print("/", m_executable->hashFor(CodeForCall));
    }
    
    if (m_structure)
        out.print(comma, "Structure: ", RawPointer(m_structure));
}
Beispiel #2
0
bool exchangeIsCompilationThread(bool newValue)
{
    initializeCompilationThreads();
    bool oldValue = isCompilationThread();
    **s_isCompilationThread = newValue;
    return oldValue;
}
void WatchpointSet::add(Watchpoint* watchpoint)
{
    ASSERT(!isCompilationThread());
    if (!watchpoint)
        return;
    m_set.push(watchpoint);
    m_isWatched = true;
}
void Database::addCompilation(CodeBlock* codeBlock, Ref<Compilation>&& compilation)
{
    LockHolder locker(m_lock);
    ASSERT(!isCompilationThread());

    m_compilations.append(compilation.copyRef());
    m_compilationMap.set(codeBlock, WTFMove(compilation));
}
Beispiel #5
0
WatchpointSet* InlineWatchpointSet::inflateSlow()
{
    ASSERT(isThin());
    ASSERT(!isCompilationThread());
    WatchpointSet* fat = adoptRef(new WatchpointSet(decodeState(m_data))).leakRef();
    WTF::storeStoreFence();
    m_data = bitwise_cast<uintptr_t>(fat);
    return fat;
}
Beispiel #6
0
void Heap::addToRememberedSet(const JSCell* cell)
{
    ASSERT(cell);
    ASSERT(!Options::enableConcurrentJIT() || !isCompilationThread());
    if (isRemembered(cell))
        return;
    const_cast<JSCell*>(cell)->setRemembered(true);
    m_slotVisitor.unconditionallyAppend(const_cast<JSCell*>(cell));
}
Beispiel #7
0
void Database::addCompilation(CodeBlock* codeBlock, PassRefPtr<Compilation> passedCompilation)
{
    LockHolder locker(m_lock);
    ASSERT(!isCompilationThread());

    RefPtr<Compilation> compilation = passedCompilation;
    
    m_compilations.append(compilation);
    m_compilationMap.set(codeBlock, compilation);
}
Beispiel #8
0
void WatchpointSet::add(Watchpoint* watchpoint)
{
    ASSERT(!isCompilationThread());
    ASSERT(state() != IsInvalidated);
    if (!watchpoint)
        return;
    m_set.push(watchpoint);
    m_setIsNotEmpty = true;
    m_state = IsWatched;
}
Beispiel #9
0
void LinkBuffer::performFinalization()
{
#ifndef NDEBUG
    ASSERT(!isCompilationThread());
    ASSERT(!m_completed);
    ASSERT(isValid());
    m_completed = true;
#endif
    
    MacroAssembler::cacheFlush(code(), m_size);
}
NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, NativeFunction constructor)
{
    ASSERT(!isCompilationThread());

    if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_pair(function, constructor)))
        return nativeExecutable;

    NativeExecutable* nativeExecutable = NativeExecutable::create(*vm, JIT::compileCTINativeCall(vm, function), function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct(vm)), constructor, NoIntrinsic);
    weakAdd(*m_hostFunctionStubMap, std::make_pair(function, constructor), Weak<NativeExecutable>(nativeExecutable));
    return nativeExecutable;
}
Beispiel #11
0
MacroAssemblerCodeRef JITThunks::ctiStub(VM* vm, ThunkGenerator generator)
{
    LockHolder locker(m_lock);
    CTIStubMap::AddResult entry = m_ctiStubMap.add(generator, MacroAssemblerCodeRef());
    if (entry.isNewEntry) {
        // Compilation thread can only retrieve existing entries.
        ASSERT(!isCompilationThread());
        entry.iterator->value = generator(vm);
    }
    return entry.iterator->value;
}
WatchpointSet* InlineWatchpointSet::inflateSlow()
{
    ASSERT(isThin());
    ASSERT(!isCompilationThread());
    WatchpointSet* fat = adoptRef(new WatchpointSet(InitializedBlind)).leakRef();
    if (m_data & IsInvalidatedFlag)
        fat->m_isInvalidated = true;
    if (m_data & IsWatchedFlag)
        fat->m_isWatched = true;
    WTF::storeStoreFence();
    m_data = bitwise_cast<uintptr_t>(fat);
    return fat;
}
Beispiel #13
0
void LinkBuffer::performFinalization()
{
#ifndef NDEBUG
    ASSERT(!isCompilationThread());
    ASSERT(!m_completed);
    ASSERT(isValid());
    m_completed = true;
#endif
    
#if ENABLE(BRANCH_COMPACTION)
    ExecutableAllocator::makeExecutable(code(), m_initialSize);
#else
    ExecutableAllocator::makeExecutable(code(), m_size);
#endif
    MacroAssembler::cacheFlush(code(), m_size);
}
bool FunctionWhitelist::contains(CodeBlock* codeBlock) const
{
    ASSERT(!isCompilationThread());
    if (!Options::dfgWhitelist())
        return true;

    if (m_entries.isEmpty())
        return false;

    String name = String::fromUTF8(codeBlock->inferredName());
    if (m_entries.contains(name))
        return true;

    String hash = String::fromUTF8(codeBlock->hashAsStringIfPossible());
    if (m_entries.contains(hash))
        return true;

    return m_entries.contains(name + '#' + hash);
}
NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, ThunkGenerator generator, Intrinsic intrinsic)
{
    ASSERT(!isCompilationThread());    

    if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_pair(function, &callHostFunctionAsConstructor)))
        return nativeExecutable;

    MacroAssemblerCodeRef code;
    if (generator) {
        if (vm->canUseJIT())
            code = generator(vm);
        else
            code = MacroAssemblerCodeRef();
    } else
        code = JIT::compileCTINativeCall(vm, function);

    NativeExecutable* nativeExecutable = NativeExecutable::create(*vm, code, function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct(vm)), callHostFunctionAsConstructor, intrinsic);
    weakAdd(*m_hostFunctionStubMap, std::make_pair(function, &callHostFunctionAsConstructor), Weak<NativeExecutable>(nativeExecutable));
    return nativeExecutable;
}
Beispiel #16
0
NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, NativeFunction constructor, ThunkGenerator generator, Intrinsic intrinsic, const String& name)
{
    ASSERT(!isCompilationThread());    
    ASSERT(vm->canUseJIT());

    if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_tuple(function, constructor, name)))
        return nativeExecutable;

    RefPtr<JITCode> forCall;
    if (generator) {
        MacroAssemblerCodeRef entry = generator(vm);
        forCall = adoptRef(new DirectJITCode(entry, entry.code(), JITCode::HostCallThunk));
    } else
        forCall = adoptRef(new NativeJITCode(JIT::compileCTINativeCall(vm, function), JITCode::HostCallThunk));
    
    RefPtr<JITCode> forConstruct = adoptRef(new NativeJITCode(MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct(vm)), JITCode::HostCallThunk));
    
    NativeExecutable* nativeExecutable = NativeExecutable::create(*vm, forCall, function, forConstruct, constructor, intrinsic, name);
    weakAdd(*m_hostFunctionStubMap, std::make_tuple(function, constructor, name), Weak<NativeExecutable>(nativeExecutable, this));
    return nativeExecutable;
}
Beispiel #17
0
void Database::addCompilation(PassRefPtr<Compilation> compilation)
{
    ASSERT(!isCompilationThread());
    
    m_compilations.append(compilation);
}
CodeLocationLabel* ArityCheckFailReturnThunks::returnPCsFor(
    VM& vm, unsigned numExpectedArgumentsIncludingThis)
{
    ASSERT(numExpectedArgumentsIncludingThis >= 1);
    
    numExpectedArgumentsIncludingThis = WTF::roundUpToMultipleOf(
        stackAlignmentRegisters(), numExpectedArgumentsIncludingThis);
    
    {
        ConcurrentJITLocker locker(m_lock);
        if (numExpectedArgumentsIncludingThis < m_nextSize)
            return m_returnPCArrays.last().get();
    }
    
    ASSERT(!isCompilationThread());
    
    numExpectedArgumentsIncludingThis = std::max(numExpectedArgumentsIncludingThis, m_nextSize * 2);
    
    AssemblyHelpers jit(&vm, 0);
    
    Vector<AssemblyHelpers::Label> labels;
    
    for (unsigned size = m_nextSize; size <= numExpectedArgumentsIncludingThis; size += stackAlignmentRegisters()) {
        labels.append(jit.label());
        
        jit.load32(
            AssemblyHelpers::Address(
                AssemblyHelpers::stackPointerRegister,
                (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) +
                PayloadOffset),
            GPRInfo::regT4);
        jit.add32(
            AssemblyHelpers::TrustedImm32(
                JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + size - 1),
            GPRInfo::regT4, GPRInfo::regT2);
        jit.lshift32(AssemblyHelpers::TrustedImm32(3), GPRInfo::regT2);
        jit.addPtr(AssemblyHelpers::stackPointerRegister, GPRInfo::regT2);
        jit.loadPtr(GPRInfo::regT2, GPRInfo::regT2);
        
        jit.addPtr(
            AssemblyHelpers::TrustedImm32(size * sizeof(Register)),
            AssemblyHelpers::stackPointerRegister);
        
        // Thunks like ours want to use the return PC to figure out where things
        // were saved. So, we pay it forward.
        jit.store32(
            GPRInfo::regT4,
            AssemblyHelpers::Address(
                AssemblyHelpers::stackPointerRegister,
                (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) +
                PayloadOffset));
        
        jit.jump(GPRInfo::regT2);
    }
    
    LinkBuffer linkBuffer(vm, &jit, GLOBAL_THUNK_ID);
    
    unsigned returnPCsSize = numExpectedArgumentsIncludingThis / stackAlignmentRegisters() + 1;
    std::unique_ptr<CodeLocationLabel[]> returnPCs =
        std::make_unique<CodeLocationLabel[]>(returnPCsSize);
    for (unsigned size = 0; size <= numExpectedArgumentsIncludingThis; size += stackAlignmentRegisters()) {
        unsigned index = size / stackAlignmentRegisters();
        RELEASE_ASSERT(index < returnPCsSize);
        if (size < m_nextSize)
            returnPCs[index] = m_returnPCArrays.last()[index];
        else
            returnPCs[index] = linkBuffer.locationOf(labels[(size - m_nextSize) / stackAlignmentRegisters()]);
    }

    CodeLocationLabel* result = returnPCs.get();

    {
        ConcurrentJITLocker locker(m_lock);
        m_returnPCArrays.append(std::move(returnPCs));
        m_refs.append(FINALIZE_CODE(linkBuffer, ("Arity check fail return thunks for up to numArgs = %u", numExpectedArgumentsIncludingThis)));
        m_nextSize = numExpectedArgumentsIncludingThis + stackAlignmentRegisters();
    }
    
    return result;
}