Esempio n. 1
0
/*
 *  internalThread -    This is the actual function called by thread when 
 *                      created a new pthread.
 */
static void *
InternalThread(void *data)
    {

    /* We save our thread id into the thread specific memory location */
    pthread_setspecific(key,data);
    printf("Tid: %d\n", *(int*)data);

    /* Initialize memory for this thread */
    memoryInit();

    int tid = *(int *)data;
    int result = eval(ThreadQueue[tid].expr,ThreadQueue[tid].env);

    if (isThrow(result) || isError(result))
        {
        P_P();
        if(StackDebugging)
            {
            printStack();
            }
        if(Debugging)
            {
            T_P();
            printf("Error in thread %d (%d)\n" ,tid,WorkingThreads);
            T_V();
            ShuttingDown = 1;
            QueueCount = 0;
            debug("EXCEPTION",error_code(result));
            scamPPFile(stdout,error_value(result));
            printf("\n");
            }
        else
            {
            if(ThreadError == -1)
                {
                ThreadError = tid;
                }
            }
        P_V();
        }

    T_P();
    --WorkingThreads;
    T_V();

    memoryShutdown();

    free(data);
    
    Thread[tid] = (pthread_t)NULL;

    pthread_exit(NULL);

    return NULL;
    }
void ShadowChicken::Packet::dump(PrintStream& out) const
{
    if (!*this) {
        out.print("empty");
        return;
    }
    
    if (isPrologue()) {
        out.print(
            "{callee = ", RawPointer(callee), ", frame = ", RawPointer(frame), ", callerFrame = ",
            RawPointer(callerFrame), "}");
        return;
    }
    
    if (isTail()) {
        out.print("tail:{frame = ", RawPointer(frame), "}");
        return;
    }
    
    ASSERT(isThrow());
    out.print("throw");
}
Esempio n. 3
0
void computeBytecodeBasicBlocks(CodeBlock* codeBlock, Vector<RefPtr<BytecodeBasicBlock> >& basicBlocks)
{
    Vector<unsigned, 32> jumpTargets;
    computePreciseJumpTargets(codeBlock, jumpTargets);

    // Create the entry and exit basic blocks.
    BytecodeBasicBlock* entry = new BytecodeBasicBlock(BytecodeBasicBlock::EntryBlock);
    basicBlocks.append(adoptRef(entry));
    BytecodeBasicBlock* exit = new BytecodeBasicBlock(BytecodeBasicBlock::ExitBlock);

    // Find basic block boundaries.
    BytecodeBasicBlock* current = new BytecodeBasicBlock(0, 0);
    linkBlocks(entry, current);
    basicBlocks.append(adoptRef(current));

    bool nextInstructionIsLeader = false;

    Interpreter* interpreter = codeBlock->vm()->interpreter;
    Instruction* instructionsBegin = codeBlock->instructions().begin();
    unsigned instructionCount = codeBlock->instructions().size();
    for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount;) {
        OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode);
        unsigned opcodeLength = opcodeLengths[opcodeID];

        bool createdBlock = false;
        // If the current bytecode is a jump target, then it's the leader of its own basic block.
        if (isJumpTarget(opcodeID, jumpTargets, bytecodeOffset) || nextInstructionIsLeader) {
            BytecodeBasicBlock* block = new BytecodeBasicBlock(bytecodeOffset, opcodeLength);
            basicBlocks.append(adoptRef(block));
            current = block;
            createdBlock = true;
            nextInstructionIsLeader = false;
            bytecodeOffset += opcodeLength;
        }

        // If the current bytecode is a branch or a return, then the next instruction is the leader of its own basic block.
        if (isBranch(opcodeID) || isTerminal(opcodeID) || isThrow(opcodeID))
            nextInstructionIsLeader = true;

        if (createdBlock)
            continue;

        // Otherwise, just add to the length of the current block.
        current->addBytecodeLength(opcodeLength);
        bytecodeOffset += opcodeLength;
    }

    // Link basic blocks together.
    for (unsigned i = 0; i < basicBlocks.size(); i++) {
        BytecodeBasicBlock* block = basicBlocks[i].get();

        if (block->isEntryBlock() || block->isExitBlock())
            continue;

        bool fallsThrough = true; 
        for (unsigned bytecodeOffset = block->leaderBytecodeOffset(); bytecodeOffset < block->leaderBytecodeOffset() + block->totalBytecodeLength();) {
            const Instruction& currentInstruction = instructionsBegin[bytecodeOffset];
            OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction.u.opcode);
            unsigned opcodeLength = opcodeLengths[opcodeID];
            // If we found a terminal bytecode, link to the exit block.
            if (isTerminal(opcodeID)) {
                ASSERT(bytecodeOffset + opcodeLength == block->leaderBytecodeOffset() + block->totalBytecodeLength());
                linkBlocks(block, exit);
                fallsThrough = false;
                break;
            }

            // If we found a throw, get the HandlerInfo for this instruction to see where we will jump. 
            // If there isn't one, treat this throw as a terminal. This is true even if we have a finally
            // block because the finally block will create its own catch, which will generate a HandlerInfo.
            if (isThrow(opcodeID)) {
                ASSERT(bytecodeOffset + opcodeLength == block->leaderBytecodeOffset() + block->totalBytecodeLength());
                HandlerInfo* handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
                fallsThrough = false;
                if (!handler) {
                    linkBlocks(block, exit);
                    break;
                }
                for (unsigned i = 0; i < basicBlocks.size(); i++) {
                    BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
                    if (handler->target == otherBlock->leaderBytecodeOffset()) {
                        linkBlocks(block, otherBlock);
                        break;
                    }
                }
                break;
            }

            // If we found a branch, link to the block(s) that we jump to.
            if (isBranch(opcodeID)) {
                ASSERT(bytecodeOffset + opcodeLength == block->leaderBytecodeOffset() + block->totalBytecodeLength());
                Vector<unsigned, 1> bytecodeOffsetsJumpedTo;
                findJumpTargetsForBytecodeOffset(codeBlock, bytecodeOffset, bytecodeOffsetsJumpedTo);

                for (unsigned i = 0; i < basicBlocks.size(); i++) {
                    BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
                    if (bytecodeOffsetsJumpedTo.contains(otherBlock->leaderBytecodeOffset()))
                        linkBlocks(block, otherBlock);
                }

                if (isUnconditionalBranch(opcodeID))
                    fallsThrough = false;

                break;
            }
            bytecodeOffset += opcodeLength;
        }

        // If we fall through then link to the next block in program order.
        if (fallsThrough) {
            ASSERT(i + 1 < basicBlocks.size());
            BytecodeBasicBlock* nextBlock = basicBlocks[i + 1].get();
            linkBlocks(block, nextBlock);
        }
    }

    basicBlocks.append(adoptRef(exit));
}
Esempio n. 4
0
void BytecodeBasicBlock::computeImpl(Block* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks)
{
    Vector<unsigned, 32> jumpTargets;
    computePreciseJumpTargets(codeBlock, instructionsBegin, instructionCount, jumpTargets);

    auto appendBlock = [&] (std::unique_ptr<BytecodeBasicBlock>&& block) {
        block->m_index = basicBlocks.size();
        basicBlocks.append(WTFMove(block));
    };

    auto linkBlocks = [&] (BytecodeBasicBlock* from, BytecodeBasicBlock* to) {
        from->addSuccessor(to);
    };

    // Create the entry and exit basic blocks.
    basicBlocks.reserveCapacity(jumpTargets.size() + 2);

    auto entry = std::make_unique<BytecodeBasicBlock>(BytecodeBasicBlock::EntryBlock);
    auto firstBlock = std::make_unique<BytecodeBasicBlock>(0, 0);
    linkBlocks(entry.get(), firstBlock.get());

    appendBlock(WTFMove(entry));
    BytecodeBasicBlock* current = firstBlock.get();
    appendBlock(WTFMove(firstBlock));

    auto exit = std::make_unique<BytecodeBasicBlock>(BytecodeBasicBlock::ExitBlock);

    bool nextInstructionIsLeader = false;

    Interpreter* interpreter = codeBlock->vm()->interpreter;
    for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount;) {
        OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset]);
        unsigned opcodeLength = opcodeLengths[opcodeID];

        bool createdBlock = false;
        // If the current bytecode is a jump target, then it's the leader of its own basic block.
        if (isJumpTarget(opcodeID, jumpTargets, bytecodeOffset) || nextInstructionIsLeader) {
            auto newBlock = std::make_unique<BytecodeBasicBlock>(bytecodeOffset, opcodeLength);
            current = newBlock.get();
            appendBlock(WTFMove(newBlock));
            createdBlock = true;
            nextInstructionIsLeader = false;
            bytecodeOffset += opcodeLength;
        }

        // If the current bytecode is a branch or a return, then the next instruction is the leader of its own basic block.
        if (isBranch(opcodeID) || isTerminal(opcodeID) || isThrow(opcodeID))
            nextInstructionIsLeader = true;

        if (createdBlock)
            continue;

        // Otherwise, just add to the length of the current block.
        current->addLength(opcodeLength);
        bytecodeOffset += opcodeLength;
    }

    // Link basic blocks together.
    for (unsigned i = 0; i < basicBlocks.size(); i++) {
        BytecodeBasicBlock* block = basicBlocks[i].get();

        if (block->isEntryBlock() || block->isExitBlock())
            continue;

        bool fallsThrough = true; 
        for (unsigned bytecodeOffset = block->leaderOffset(); bytecodeOffset < block->leaderOffset() + block->totalLength();) {
            OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset]);
            unsigned opcodeLength = opcodeLengths[opcodeID];
            // If we found a terminal bytecode, link to the exit block.
            if (isTerminal(opcodeID)) {
                ASSERT(bytecodeOffset + opcodeLength == block->leaderOffset() + block->totalLength());
                linkBlocks(block, exit.get());
                fallsThrough = false;
                break;
            }

            // If we found a throw, get the HandlerInfo for this instruction to see where we will jump. 
            // If there isn't one, treat this throw as a terminal. This is true even if we have a finally
            // block because the finally block will create its own catch, which will generate a HandlerInfo.
            if (isThrow(opcodeID)) {
                ASSERT(bytecodeOffset + opcodeLength == block->leaderOffset() + block->totalLength());
                auto* handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
                fallsThrough = false;
                if (!handler) {
                    linkBlocks(block, exit.get());
                    break;
                }
                for (unsigned i = 0; i < basicBlocks.size(); i++) {
                    BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
                    if (handler->target == otherBlock->leaderOffset()) {
                        linkBlocks(block, otherBlock);
                        break;
                    }
                }
                break;
            }

            // If we found a branch, link to the block(s) that we jump to.
            if (isBranch(opcodeID)) {
                ASSERT(bytecodeOffset + opcodeLength == block->leaderOffset() + block->totalLength());
                Vector<unsigned, 1> bytecodeOffsetsJumpedTo;
                findJumpTargetsForBytecodeOffset(codeBlock, instructionsBegin, bytecodeOffset, bytecodeOffsetsJumpedTo);

                for (unsigned i = 0; i < basicBlocks.size(); i++) {
                    BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
                    if (bytecodeOffsetsJumpedTo.contains(otherBlock->leaderOffset()))
                        linkBlocks(block, otherBlock);
                }

                if (isUnconditionalBranch(opcodeID))
                    fallsThrough = false;

                break;
            }
            bytecodeOffset += opcodeLength;
        }

        // If we fall through then link to the next block in program order.
        if (fallsThrough) {
            ASSERT(i + 1 < basicBlocks.size());
            BytecodeBasicBlock* nextBlock = basicBlocks[i + 1].get();
            linkBlocks(block, nextBlock);
        }
    }

    appendBlock(WTFMove(exit));
    
    for (auto& basicBlock : basicBlocks)
        basicBlock->shrinkToFit();
}
void BytecodeBasicBlock::computeImpl(Block* codeBlock, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks)
{
    Vector<InstructionStream::Offset, 32> jumpTargets;
    computePreciseJumpTargets(codeBlock, instructions, jumpTargets);

    auto appendBlock = [&] (std::unique_ptr<BytecodeBasicBlock>&& block) {
        block->m_index = basicBlocks.size();
        basicBlocks.append(WTFMove(block));
    };

    auto linkBlocks = [&] (BytecodeBasicBlock* from, BytecodeBasicBlock* to) {
        from->addSuccessor(to);
    };

    // Create the entry and exit basic blocks.
    basicBlocks.reserveCapacity(jumpTargets.size() + 2);

    auto entry = std::make_unique<BytecodeBasicBlock>(BytecodeBasicBlock::EntryBlock);
    auto firstBlock = std::make_unique<BytecodeBasicBlock>(BytecodeBasicBlock::EntryBlock);
    linkBlocks(entry.get(), firstBlock.get());

    appendBlock(WTFMove(entry));
    BytecodeBasicBlock* current = firstBlock.get();
    appendBlock(WTFMove(firstBlock));

    auto exit = std::make_unique<BytecodeBasicBlock>(BytecodeBasicBlock::ExitBlock);

    bool nextInstructionIsLeader = false;

    for (const auto& instruction : instructions) {
        auto bytecodeOffset = instruction.offset();
        OpcodeID opcodeID = instruction->opcodeID();

        bool createdBlock = false;
        // If the current bytecode is a jump target, then it's the leader of its own basic block.
        if (isJumpTarget(opcodeID, jumpTargets, bytecodeOffset) || nextInstructionIsLeader) {
            auto newBlock = std::make_unique<BytecodeBasicBlock>(instruction);
            current = newBlock.get();
            appendBlock(WTFMove(newBlock));
            createdBlock = true;
            nextInstructionIsLeader = false;
        }

        // If the current bytecode is a branch or a return, then the next instruction is the leader of its own basic block.
        if (isBranch(opcodeID) || isTerminal(opcodeID) || isThrow(opcodeID))
            nextInstructionIsLeader = true;

        if (createdBlock)
            continue;

        // Otherwise, just add to the length of the current block.
        current->addLength(instruction->size());
    }

    // Link basic blocks together.
    for (unsigned i = 0; i < basicBlocks.size(); i++) {
        BytecodeBasicBlock* block = basicBlocks[i].get();

        if (block->isEntryBlock() || block->isExitBlock())
            continue;

        bool fallsThrough = true;
        for (auto bytecodeOffset : block->offsets()) {
            auto instruction = instructions.at(bytecodeOffset);
            OpcodeID opcodeID = instruction->opcodeID();

            // If we found a terminal bytecode, link to the exit block.
            if (isTerminal(opcodeID)) {
                ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength());
                linkBlocks(block, exit.get());
                fallsThrough = false;
                break;
            }

            // If we found a throw, get the HandlerInfo for this instruction to see where we will jump.
            // If there isn't one, treat this throw as a terminal. This is true even if we have a finally
            // block because the finally block will create its own catch, which will generate a HandlerInfo.
            if (isThrow(opcodeID)) {
                ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength());
                auto* handler = codeBlock->handlerForBytecodeOffset(instruction.offset());
                fallsThrough = false;
                if (!handler) {
                    linkBlocks(block, exit.get());
                    break;
                }
                for (unsigned i = 0; i < basicBlocks.size(); i++) {
                    BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
                    if (handler->target == otherBlock->leaderOffset()) {
                        linkBlocks(block, otherBlock);
                        break;
                    }
                }
                break;
            }

            // If we found a branch, link to the block(s) that we jump to.
            if (isBranch(opcodeID)) {
                ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength());
                Vector<InstructionStream::Offset, 1> bytecodeOffsetsJumpedTo;
                findJumpTargetsForInstruction(codeBlock, instruction, bytecodeOffsetsJumpedTo);

                size_t numberOfJumpTargets = bytecodeOffsetsJumpedTo.size();
                ASSERT(numberOfJumpTargets);
                for (unsigned i = 0; i < basicBlocks.size(); i++) {
                    BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
                    if (bytecodeOffsetsJumpedTo.contains(otherBlock->leaderOffset())) {
                        linkBlocks(block, otherBlock);
                        --numberOfJumpTargets;
                        if (!numberOfJumpTargets)
                            break;
                    }
                }
                // numberOfJumpTargets may not be 0 here if there are multiple jumps targeting the same
                // basic blocks (e.g. in a switch type opcode). Since we only decrement numberOfJumpTargets
                // once per basic block, the duplicates are not accounted for. For our purpose here,
                // that doesn't matter because we only need to link to the target block once regardless
                // of how many ways this block can jump there.

                if (isUnconditionalBranch(opcodeID))
                    fallsThrough = false;

                break;
            }
        }

        // If we fall through then link to the next block in program order.
        if (fallsThrough) {
            ASSERT(i + 1 < basicBlocks.size());
            BytecodeBasicBlock* nextBlock = basicBlocks[i + 1].get();
            linkBlocks(block, nextBlock);
        }
    }

    appendBlock(WTFMove(exit));

    for (auto& basicBlock : basicBlocks)
        basicBlock->shrinkToFit();
}