예제 #1
0
// Parsing the file is somewhat expensive since we have to shell out to cpython;
// it's not a huge deal right now, but this caching version can significantly cut down
// on the startup time (40ms -> 10ms).
AST_Module* caching_parse(const char* fn) {
    Timer _t("parsing");

    int code;
    std::string cache_fn = std::string(fn) + "c";

    struct stat source_stat, cache_stat;
    code = stat(fn, &source_stat);
    assert(code == 0);
    code = stat(cache_fn.c_str(), &cache_stat);
    if (code != 0 || cache_stat.st_mtime < source_stat.st_mtime ||
            (cache_stat.st_mtime == source_stat.st_mtime && cache_stat.st_mtim.tv_nsec < source_stat.st_mtim.tv_nsec)) {
        _reparse(fn, cache_fn);
    }

    FILE *fp = fopen(cache_fn.c_str(), "r");
    assert(fp);

    while (true) {
        char buf[MAGIC_STRING_LENGTH];
        int read = fread(buf, 1, MAGIC_STRING_LENGTH, fp);
        if (read != 4 || strncmp(buf, MAGIC_STRING, MAGIC_STRING_LENGTH) != 0) {
            fclose(fp);
            _reparse(fn, cache_fn);

            fp = fopen(cache_fn.c_str(), "r");
            assert(fp);
        } else {
            break;
        }
    }

    BufferedReader *reader = new BufferedReader(fp);
    AST* rtn = readASTMisc(reader);
    reader->fill();
    assert(reader->bytesBuffered() == 0);
    delete reader;

    assert(rtn->type == AST_TYPE::Module);

    long us = _t.end();
    static StatCounter us_parsing("us_parsing");
    us_parsing.log(us);

    return static_cast<AST_Module*>(rtn);
}
예제 #2
0
// Parsing the file is somewhat expensive since we have to shell out to cpython;
// it's not a huge deal right now, but this caching version can significantly cut down
// on the startup time (40ms -> 10ms).
AST_Module* caching_parse(const char* fn) {
    Timer _t("parsing");

    int code;
    std::string cache_fn = std::string(fn) + "c";

    struct stat source_stat, cache_stat;
    code = stat(fn, &source_stat);
    assert(code == 0);
    code = stat(cache_fn.c_str(), &cache_stat);
    if (code != 0 || cache_stat.st_mtime < source_stat.st_mtime
        || (cache_stat.st_mtime == source_stat.st_mtime && cache_stat.st_mtim.tv_nsec < source_stat.st_mtim.tv_nsec)) {
        _reparse(fn, cache_fn);
        code = stat(cache_fn.c_str(), &cache_stat);
        assert(code == 0);
    }

    FILE* fp = fopen(cache_fn.c_str(), "r");
    assert(fp);

    while (true) {
        bool good = true;

        if (good) {
            char buf[MAGIC_STRING_LENGTH];
            int read = fread(buf, 1, MAGIC_STRING_LENGTH, fp);
            if (read != MAGIC_STRING_LENGTH || strncmp(buf, MAGIC_STRING, MAGIC_STRING_LENGTH) != 0) {
                if (VERBOSITY()) {
                    printf("Warning: corrupt or non-Pyston .pyc file found; ignoring\n");
                }
                good = false;
            }
        }

        if (good) {
            int length = 0;
            fseek(fp, MAGIC_STRING_LENGTH, SEEK_SET);
            static_assert(sizeof(length) >= CHECKSUM_LENGTH, "");
            int read = fread(&length, 1, CHECKSUM_LENGTH, fp);

            int expected_total_length = MAGIC_STRING_LENGTH + CHECKSUM_LENGTH + length;

            if (read != CHECKSUM_LENGTH || expected_total_length != cache_stat.st_size) {
                if (VERBOSITY()) {
                    printf("Warning: truncated .pyc file found; ignoring\n");
                }
                good = false;
            }
        }

        if (!good) {
            fclose(fp);
            _reparse(fn, cache_fn);
            code = stat(cache_fn.c_str(), &cache_stat);
            assert(code == 0);

            fp = fopen(cache_fn.c_str(), "r");
            assert(fp);
        } else {
            break;
        }
    }

    BufferedReader* reader = new BufferedReader(fp);
    AST* rtn = readASTMisc(reader);
    reader->fill();
    assert(reader->bytesBuffered() == 0);
    delete reader;

    assert(rtn->type == AST_TYPE::Module);

    long us = _t.end();
    static StatCounter us_parsing("us_parsing");
    us_parsing.log(us);

    return ast_cast<AST_Module>(rtn);
}
예제 #3
0
파일: parser.cpp 프로젝트: lyzardiar/pyston
// Parsing the file is somewhat expensive since we have to shell out to cpython;
// it's not a huge deal right now, but this caching version can significantly cut down
// on the startup time (40ms -> 10ms).
AST_Module* caching_parse_file(const char* fn) {
    STAT_TIMER(t0, "us_timer_caching_parse_file");
    static StatCounter us_parsing("us_parsing");
    Timer _t("parsing");
    _t.setExitCallback([](uint64_t t) { us_parsing.log(t); });

    int code;
    std::string cache_fn = std::string(fn) + "c";

    struct stat source_stat, cache_stat;
    code = stat(fn, &source_stat);
    assert(code == 0);
    code = stat(cache_fn.c_str(), &cache_stat);
    if (code != 0 || cache_stat.st_mtime < source_stat.st_mtime
        || (cache_stat.st_mtime == source_stat.st_mtime && cache_stat.st_mtim.tv_nsec < source_stat.st_mtim.tv_nsec)) {
        AST_Module* mod = 0;
        auto result = _reparse(fn, cache_fn, mod);
        if (mod)
            return mod;

        if (result == ParseResult::FAILURE)
            return NULL;

        if (result == ParseResult::PYC_UNWRITABLE)
            return parse_file(fn);

        code = stat(cache_fn.c_str(), &cache_stat);
        assert(code == 0);
    }

    FILE* fp = fopen(cache_fn.c_str(), "r");
    assert(fp);

    while (true) {
        bool good = true;

        if (good) {
            char buf[MAGIC_STRING_LENGTH];
            int read = fread(buf, 1, MAGIC_STRING_LENGTH, fp);
            if (read != MAGIC_STRING_LENGTH || strncmp(buf, getMagic(), MAGIC_STRING_LENGTH) != 0) {
                if (VERBOSITY()) {
                    printf("Warning: corrupt or non-Pyston .pyc file found; ignoring\n");
                }
                good = false;
            }
        }

        if (good) {
            int length = 0;
            fseek(fp, MAGIC_STRING_LENGTH, SEEK_SET);
            static_assert(sizeof(length) >= CHECKSUM_LENGTH, "");
            int read = fread(&length, 1, CHECKSUM_LENGTH, fp);

            int expected_total_length = MAGIC_STRING_LENGTH + CHECKSUM_LENGTH + length;

            if (read != CHECKSUM_LENGTH || expected_total_length != cache_stat.st_size) {
                if (VERBOSITY()) {
                    printf("Warning: truncated .pyc file found; ignoring\n");
                }
                good = false;
            }
        }

        if (!good) {
            fclose(fp);
            AST_Module* mod = 0;
            auto result = _reparse(fn, cache_fn, mod);
            if (mod)
                return mod;

            if (result == ParseResult::FAILURE)
                return NULL;

            if (result == ParseResult::PYC_UNWRITABLE)
                return parse_file(fn);

            code = stat(cache_fn.c_str(), &cache_stat);
            assert(code == 0);

            fp = fopen(cache_fn.c_str(), "r");
            assert(fp);
        } else {
            break;
        }
    }

    BufferedReader* reader = new BufferedReader(fp);
    AST* rtn = readASTMisc(reader);
    reader->fill();
    assert(reader->bytesBuffered() == 0);
    delete reader;

    fclose(fp);

    assert(rtn->type == AST_TYPE::Module);

    return ast_cast<AST_Module>(rtn);
}