コード例 #1
0
ファイル: ics.cpp プロジェクト: jmgc/pyston
RuntimeIC::RuntimeIC(void* func_addr, int num_slots, int slot_size) : eh_frame(RUNTIMEICS_OMIT_FRAME_PTR) {
    static StatCounter sc("runtime_ics_num");
    sc.log();

    if (ENABLE_RUNTIME_ICS) {
        assert(SCRATCH_BYTES >= 0);
        assert(SCRATCH_BYTES < 0x80); // This would break both the instruction encoding and the dwarf encoding
        assert(SCRATCH_BYTES % 8 == 0);

#if RUNTIMEICS_OMIT_FRAME_PTR
        /*
         * prologue:
         * sub $0x28, %rsp  # 48 83 ec 28
         *
         * epilogue:
         * add $0x28, %rsp  # 48 83 c4 28
         * retq             # c3
         *
         */
        static const int PROLOGUE_SIZE = 4;
        static const int EPILOGUE_SIZE = 5;
        assert(SCRATCH_BYTES % 16 == 8);
#else
        /*
         * The prologue looks like:
         * push %rbp        # 55
         * mov %rsp, %rbp   # 48 89 e5
         * sub $0x30, %rsp  # 48 83 ec 30
         *
         * The epilogue is:
         * add $0x30, %rsp  # 48 83 c4 30
         * pop %rbp         # 5d
         * retq             # c3
         */
        static const int PROLOGUE_SIZE = 8;
        static const int EPILOGUE_SIZE = 6;
        assert(SCRATCH_BYTES % 16 == 0);
#endif
        static const int CALL_SIZE = 13;

        int patchable_size = num_slots * slot_size;

#ifdef NVALGRIND
        int total_size = PROLOGUE_SIZE + patchable_size + CALL_SIZE + EPILOGUE_SIZE;
        addr = malloc(total_size);
#else
        total_size = PROLOGUE_SIZE + patchable_size + CALL_SIZE + EPILOGUE_SIZE;
        addr = mmap(NULL, (total_size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1), PROT_READ | PROT_WRITE | PROT_EXEC,
                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        RELEASE_ASSERT(addr != MAP_FAILED, "");
#endif

        // printf("Allocated runtime IC at %p\n", addr);

        std::unique_ptr<ICSetupInfo> setup_info(
            ICSetupInfo::initialize(true, num_slots, slot_size, ICSetupInfo::Generic, NULL));
        uint8_t* pp_start = (uint8_t*)addr + PROLOGUE_SIZE;
        uint8_t* pp_end = pp_start + patchable_size + CALL_SIZE;


        SpillMap _spill_map;
        PatchpointInitializationInfo initialization_info
            = initializePatchpoint3(func_addr, pp_start, pp_end, 0 /* scratch_offset */, 0 /* scratch_size */,
                                    std::unordered_set<int>(), _spill_map);
        assert(_spill_map.size() == 0);
        assert(initialization_info.slowpath_start == pp_start + patchable_size);
        assert(initialization_info.slowpath_rtn_addr == pp_end);
        assert(initialization_info.continue_addr == pp_end);

        StackInfo stack_info(SCRATCH_BYTES, 0);
        icinfo = registerCompiledPatchpoint(pp_start, pp_start + patchable_size, pp_end, pp_end, setup_info.get(),
                                            stack_info, std::unordered_set<int>());

        assembler::Assembler prologue_assem((uint8_t*)addr, PROLOGUE_SIZE);
#if RUNTIMEICS_OMIT_FRAME_PTR
        // If SCRATCH_BYTES is 8 or less, we could use more compact instruction encodings
        // (push instead of sub), but it doesn't seem worth it for now.
        prologue_assem.sub(assembler::Immediate(SCRATCH_BYTES), assembler::RSP);
#else
        prologue_assem.push(assembler::RBP);
        prologue_assem.mov(assembler::RSP, assembler::RBP);
        prologue_assem.sub(assembler::Immediate(SCRATCH_BYTES), assembler::RSP);
#endif
        assert(!prologue_assem.hasFailed());
        assert(prologue_assem.isExactlyFull());

        assembler::Assembler epilogue_assem(pp_end, EPILOGUE_SIZE);
#if RUNTIMEICS_OMIT_FRAME_PTR
        epilogue_assem.add(assembler::Immediate(SCRATCH_BYTES), assembler::RSP);
#else
        epilogue_assem.add(assembler::Immediate(SCRATCH_BYTES), assembler::RSP);
        epilogue_assem.pop(assembler::RBP);
#endif
        epilogue_assem.retq();
        assert(!epilogue_assem.hasFailed());
        assert(epilogue_assem.isExactlyFull());

        // TODO: ideally would be more intelligent about allocation strategies.
        // The code sections should be together and the eh sections together
        eh_frame.writeAndRegister(addr, total_size);
    } else {
        addr = func_addr;
    }
}
コード例 #2
0
ファイル: ics.cpp プロジェクト: Daetalus/pyston
RuntimeIC::RuntimeIC(void* func_addr, int total_size) {
    static StatCounter sc("num_runtime_ics");
    sc.log();

    if (ENABLE_RUNTIME_ICS) {
        assert(SCRATCH_BYTES >= 0);
        assert(SCRATCH_BYTES < 0x80); // This would break both the instruction encoding and the dwarf encoding
        assert(SCRATCH_BYTES % 8 == 0);

#if RUNTIMEICS_OMIT_FRAME_PTR
        /*
         * prologue:
         * sub $0x28, %rsp  # 48 83 ec 28
         *
         * epilogue:
         * add $0x28, %rsp  # 48 83 c4 28
         * retq             # c3
         *
         */
        static const int PROLOGUE_SIZE = 4;
        static const int EPILOGUE_SIZE = 5;
        assert(SCRATCH_BYTES % 16 == 8);
#else
        /*
         * The prologue looks like:
         * push %rbp        # 55
         * mov %rsp, %rbp   # 48 89 e5
         * sub $0x30, %rsp  # 48 83 ec 30
         *
         * The epilogue is:
         * add $0x30, %rsp  # 48 83 c4 30
         * pop %rbp         # 5d
         * retq             # c3
         */
        static const int PROLOGUE_SIZE = 8;
        static const int EPILOGUE_SIZE = 6;
        assert(SCRATCH_BYTES % 16 == 0);
#endif
        static const int CALL_SIZE = 13;

        int total_code_size = total_size - EH_FRAME_SIZE;
        int patchable_size = total_code_size - (PROLOGUE_SIZE + CALL_SIZE + EPILOGUE_SIZE);

        int total_size = total_code_size + EH_FRAME_SIZE;
        assert(total_size == 512 && "we currently only have a 512 byte block memory manager");
        addr = memory_manager_512b.alloc();

        // the memory block contains the EH frame directly followed by the generated machine code.
        void* eh_frame_addr = addr;
        addr = (char*)addr + EH_FRAME_SIZE;

        // printf("Allocated runtime IC at %p\n", addr);

        std::unique_ptr<ICSetupInfo> setup_info(ICSetupInfo::initialize(true, patchable_size, ICSetupInfo::Generic));
        uint8_t* pp_start = (uint8_t*)addr + PROLOGUE_SIZE;
        uint8_t* pp_end = pp_start + patchable_size + CALL_SIZE;


        SpillMap _spill_map;
        PatchpointInitializationInfo initialization_info = initializePatchpoint3(
            func_addr, pp_start, pp_end, 0 /* scratch_offset */, 0 /* scratch_size */, LiveOutSet(), _spill_map);
        assert(_spill_map.size() == 0);
        assert(initialization_info.slowpath_start == pp_start + patchable_size);
        assert(initialization_info.slowpath_rtn_addr == pp_end);
        assert(initialization_info.continue_addr == pp_end);

        StackInfo stack_info(SCRATCH_BYTES, 0);
        icinfo = registerCompiledPatchpoint(pp_start, pp_start + patchable_size, pp_end, pp_end, setup_info.get(),
                                            stack_info, LiveOutSet());

        assembler::Assembler prologue_assem((uint8_t*)addr, PROLOGUE_SIZE);
#if RUNTIMEICS_OMIT_FRAME_PTR
        // If SCRATCH_BYTES is 8 or less, we could use more compact instruction encodings
        // (push instead of sub), but it doesn't seem worth it for now.
        prologue_assem.sub(assembler::Immediate(SCRATCH_BYTES), assembler::RSP);
#else
        prologue_assem.push(assembler::RBP);
        prologue_assem.mov(assembler::RSP, assembler::RBP);
        prologue_assem.sub(assembler::Immediate(SCRATCH_BYTES), assembler::RSP);
#endif
        assert(!prologue_assem.hasFailed());
        assert(prologue_assem.isExactlyFull());

        assembler::Assembler epilogue_assem(pp_end, EPILOGUE_SIZE);
#if RUNTIMEICS_OMIT_FRAME_PTR
        epilogue_assem.add(assembler::Immediate(SCRATCH_BYTES), assembler::RSP);
#else
        epilogue_assem.add(assembler::Immediate(SCRATCH_BYTES), assembler::RSP);
        epilogue_assem.pop(assembler::RBP);
#endif
        epilogue_assem.retq();
        assert(!epilogue_assem.hasFailed());
        assert(epilogue_assem.isExactlyFull());


        if (RUNTIMEICS_OMIT_FRAME_PTR)
            memcpy(eh_frame_addr, _eh_frame_template_ofp, _eh_frame_template_ofp_size);
        else
            memcpy(eh_frame_addr, _eh_frame_template_fp, _eh_frame_template_fp_size);
        register_eh_frame.updateAndRegisterFrameFromTemplate((uint64_t)addr, total_code_size, (uint64_t)eh_frame_addr,
                                                             EH_FRAME_SIZE);
    } else {
        addr = func_addr;
    }
}