diff options
Diffstat (limited to 'ThirdParty/tolua_runtime/luajit-2.1/src/x64')
13 files changed, 909 insertions, 0 deletions
diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/Makefile b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/Makefile new file mode 100644 index 0000000..2727714 --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/Makefile @@ -0,0 +1,13 @@ +.PHONY: default test benchmark clean + +default: + @echo "make target include: test bechmark clean" + +test: + $(MAKE) -C test test + +benchmark: + $(MAKE) -C test benchmark + +clean: + $(MAKE) -C test clean diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/src/lj_str_hash_x64.h b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/src/lj_str_hash_x64.h new file mode 100644 index 0000000..cf37a2d --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/src/lj_str_hash_x64.h @@ -0,0 +1,271 @@ +/* + * This file defines string hash function using CRC32. It takes advantage of + * Intel hardware support (crc32 instruction, SSE 4.2) to speedup the CRC32 + * computation. The hash functions try to compute CRC32 of length and up + * to 128 bytes of given string. + */ + +#ifndef _LJ_STR_HASH_X64_H_ +#define _LJ_STR_HASH_X64_H_ + +#if defined(__SSE4_2__) && defined(__x86_64) && defined(__GNUC__) + +#include <stdint.h> +#include <sys/types.h> +#include <unistd.h> +#include <time.h> +#include <smmintrin.h> + +#include "../../lj_def.h" + +#undef LJ_AINLINE +#define LJ_AINLINE + +#ifdef __MINGW32__ +#define random() ((long) rand()) +#define srandom(seed) srand(seed) +#endif + +static const uint64_t* cast_uint64p(const char* str) +{ + return (const uint64_t*)(void*)str; +} + +static const uint32_t* cast_uint32p(const char* str) +{ + return (const uint32_t*)(void*)str; +} + +/* hash string with len in [1, 4) */ +static LJ_AINLINE uint32_t lj_str_hash_1_4(const char* str, uint32_t len) +{ +#if 0 + /* TODO: The if-1 part (i.e the original algorithm) is working better when + * the load-factor is high, as revealed by conflict benchmark (via + * 'make benchmark' command); need to understand why it's so. + */ + uint32_t v = str[0]; + v = (v << 8) | str[len >> 1]; + v = (v << 8) | str[len - 1]; + v = (v << 8) | len; + return _mm_crc32_u32(0, v); +#else + uint32_t a, b, h = len; + + a = *(const uint8_t *)str; + h ^= *(const uint8_t *)(str+len-1); + b = *(const uint8_t *)(str+(len>>1)); + h ^= b; h -= lj_rol(b, 14); + + a ^= h; a -= lj_rol(h, 11); + b ^= a; b -= lj_rol(a, 25); + h ^= b; h -= lj_rol(b, 16); + + return h; +#endif +} + +/* hash string with len in [4, 16) */ +static LJ_AINLINE uint32_t lj_str_hash_4_16(const char* str, uint32_t len) +{ + uint64_t v1, v2, h; + + if (len >= 8) { + v1 = *cast_uint64p(str); + v2 = *cast_uint64p(str + len - 8); + } else { + v1 = *cast_uint32p(str); + v2 = *cast_uint32p(str + len - 4); + } + + h = _mm_crc32_u32(0, len); + h = _mm_crc32_u64(h, v1); + h = _mm_crc32_u64(h, v2); + return h; +} + +/* hash string with length in [16, 128) */ +static uint32_t lj_str_hash_16_128(const char* str, uint32_t len) +{ + uint64_t h1, h2; + uint32_t i; + + h1 = _mm_crc32_u32(0, len); + h2 = 0; + + for (i = 0; i < len - 16; i += 16) { + h1 += _mm_crc32_u64(h1, *cast_uint64p(str + i)); + h2 += _mm_crc32_u64(h2, *cast_uint64p(str + i + 8)); + }; + + h1 = _mm_crc32_u64(h1, *cast_uint64p(str + len - 16)); + h2 = _mm_crc32_u64(h2, *cast_uint64p(str + len - 8)); + + return _mm_crc32_u32(h1, h2); +} + +/* ************************************************************************** + * + * Following is code about hashing string with length >= 128 + * + * ************************************************************************** + */ +static uint32_t random_pos[32][2]; +static const int8_t log2_tab[128] = { -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 }; + +/* return floor(log2(n)) */ +static LJ_AINLINE uint32_t log2_floor(uint32_t n) +{ + if (n <= 127) { + return log2_tab[n]; + } + + if ((n >> 8) <= 127) { + return log2_tab[n >> 8] + 8; + } + + if ((n >> 16) <= 127) { + return log2_tab[n >> 16] + 16; + } + + if ((n >> 24) <= 127) { + return log2_tab[n >> 24] + 24; + } + + return 31; +} + +#define POW2_MASK(n) ((1L << (n)) - 1) + +/* This function is to populate `random_pos` such that random_pos[i][*] + * contains random value in the range of [2**i, 2**(i+1)). + */ +static void x64_init_random(void) +{ + int i, seed, rml; + + /* Calculate the ceil(log2(RAND_MAX)) */ + rml = log2_floor(RAND_MAX); + if (RAND_MAX & (RAND_MAX - 1)) { + rml += 1; + } + + /* Init seed */ + seed = _mm_crc32_u32(0, getpid()); + seed = _mm_crc32_u32(seed, time(NULL)); + srandom(seed); + + /* Now start to populate the random_pos[][]. */ + for (i = 0; i < 3; i++) { + /* No need to provide random value for chunk smaller than 8 bytes */ + random_pos[i][0] = random_pos[i][1] = 0; + } + + for (; i < rml; i++) { + random_pos[i][0] = random() & POW2_MASK(i+1); + random_pos[i][1] = random() & POW2_MASK(i+1); + } + + for (; i < 31; i++) { + int j; + for (j = 0; j < 2; j++) { + uint32_t v, scale; + scale = random_pos[i - rml][0]; + if (scale == 0) { + scale = 1; + } + v = (random() * scale) & POW2_MASK(i+1); + random_pos[i][j] = v; + } + } +} +#undef POW2_MASK + +void __attribute__((constructor)) x64_init_random_constructor() +{ + x64_init_random(); +} + +/* Return a pre-computed random number in the range of [1**chunk_sz_order, + * 1**(chunk_sz_order+1)). It is "unsafe" in the sense that the return value + * may be greater than chunk-size; it is up to the caller to make sure + * "chunk-base + return-value-of-this-func" has valid virtual address. + */ +static LJ_AINLINE uint32_t get_random_pos_unsafe(uint32_t chunk_sz_order, + uint32_t idx) +{ + uint32_t pos = random_pos[chunk_sz_order][idx & 1]; + return pos; +} + +static LJ_NOINLINE uint32_t lj_str_hash_128_above(const char* str, + uint32_t len) +{ + uint32_t chunk_num, chunk_sz, chunk_sz_log2, i, pos1, pos2; + uint64_t h1, h2, v; + const char* chunk_ptr; + + chunk_num = 16; + chunk_sz = len / chunk_num; + chunk_sz_log2 = log2_floor(chunk_sz); + + pos1 = get_random_pos_unsafe(chunk_sz_log2, 0); + pos2 = get_random_pos_unsafe(chunk_sz_log2, 1); + + h1 = _mm_crc32_u32(0, len); + h2 = 0; + + /* loop over 14 chunks, 2 chunks at a time */ + for (i = 0, chunk_ptr = str; i < (chunk_num / 2 - 1); + chunk_ptr += chunk_sz, i++) { + + v = *cast_uint64p(chunk_ptr + pos1); + h1 = _mm_crc32_u64(h1, v); + + v = *cast_uint64p(chunk_ptr + chunk_sz + pos2); + h2 = _mm_crc32_u64(h2, v); + } + + /* the last two chunks */ + v = *cast_uint64p(chunk_ptr + pos1); + h1 = _mm_crc32_u64(h1, v); + + v = *cast_uint64p(chunk_ptr + chunk_sz - 8 - pos2); + h2 = _mm_crc32_u64(h2, v); + + /* process the trailing part */ + h1 = _mm_crc32_u64(h1, *cast_uint64p(str)); + h2 = _mm_crc32_u64(h2, *cast_uint64p(str + len - 8)); + + h1 = _mm_crc32_u32(h1, h2); + return h1; +} + +/* NOTE: the "len" should not be zero */ +static LJ_AINLINE uint32_t lj_str_hash(const char* str, size_t len) +{ + if (len < 128) { + if (len >= 16) { /* [16, 128) */ + return lj_str_hash_16_128(str, len); + } + + if (len >= 4) { /* [4, 16) */ + return lj_str_hash_4_16(str, len); + } + + /* [0, 4) */ + return lj_str_hash_1_4(str, len); + } + /* [128, inf) */ + return lj_str_hash_128_above(str, len); +} + +#define LJ_ARCH_STR_HASH lj_str_hash +#else +#undef LJ_ARCH_STR_HASH +#endif +#endif /*_LJ_STR_HASH_X64_H_*/ diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/Makefile b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/Makefile new file mode 100644 index 0000000..3ec44ea --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/Makefile @@ -0,0 +1,48 @@ +.PHONY: default test benchmark + +default: test benchmark + +COMMON_OBJ := test_util.o + +TEST_PROGRAM := ht_test +BENCHMARK_PROGRAM := ht_benchmark + +TEST_PROGRAM_OBJ := $(COMMON_OBJ) test.o +BENCHMARK_PROGRAM_OBJ := $(COMMON_OBJ) benchmark.o + +ifeq ($(WITH_VALGRIND), 1) + VALGRIND := valgrind --leak-check=full +else + VALGRIND := +endif + +CXXFLAGS := -O3 -MD -g -msse4.2 -Wall -I../src -I../../../src + +%.o: %.cxx + $(CXX) $(CXXFLAGS) -MD -c $< + +test: $(TEST_PROGRAM) + @echo "some unit test" + $(VALGRIND) ./$(TEST_PROGRAM) + ./unit_test.sh + + @echo "smoke test" + ../../luajit test_str_comp.lua + +benchmark: $(BENCHMARK_PROGRAM) + # micro benchmark + ./$(BENCHMARK_PROGRAM) + +$(TEST_PROGRAM) : $(TEST_PROGRAM_OBJ) + cat $(TEST_PROGRAM_OBJ:.o=.d) > dep1.txt + $(CXX) $+ $(CXXFLAGS) -lm -o $@ + +$(BENCHMARK_PROGRAM): $(BENCHMARK_PROGRAM_OBJ) + cat $(BENCHMARK_PROGRAM_OBJ:.o=.d) > dep2.txt + $(CXX) $+ $(CXXFLAGS) -o $@ + +-include dep1.txt +-include dep2.txt + +clean: + -rm -f *.o *.d dep*.txt $(BENCHMARK_PROGRAM) $(TEST_PROGRAM) diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/benchmark.cxx b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/benchmark.cxx new file mode 100644 index 0000000..e37edb0 --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/benchmark.cxx @@ -0,0 +1,278 @@ +#include <sys/time.h> // for gettimeofday() +extern "C" { +#include "lj_str_hash_x64.h" +} +#include <string> +#include <vector> +#include <utility> +#include <algorithm> +#include "test_util.hpp" +#include <stdio.h> +#include <math.h> + +using namespace std; + +#define lj_rol(x, n) (((x)<<(n)) | ((x)>>(-(int)(n)&(8*sizeof(x)-1)))) +#define lj_ror(x, n) (((x)<<(-(int)(n)&(8*sizeof(x)-1))) | ((x)>>(n))) + +const char* separator = "-------------------------------------------"; + +static uint32_t LJ_AINLINE +lj_original_hash(const char *str, size_t len) +{ + uint32_t a, b, h = len; + if (len >= 4) { + a = lj_getu32(str); h ^= lj_getu32(str+len-4); + b = lj_getu32(str+(len>>1)-2); + h ^= b; h -= lj_rol(b, 14); + b += lj_getu32(str+(len>>2)-1); + a ^= h; a -= lj_rol(h, 11); + b ^= a; b -= lj_rol(a, 25); + h ^= b; h -= lj_rol(b, 16); + } else { + a = *(const uint8_t *)str; + h ^= *(const uint8_t *)(str+len-1); + b = *(const uint8_t *)(str+(len>>1)); + h ^= b; h -= lj_rol(b, 14); + } + + a ^= h; a -= lj_rol(h, 11); + b ^= a; b -= lj_rol(a, 25); + h ^= b; h -= lj_rol(b, 16); + + return h; +} + +template<class T> double +BenchmarkHashTmpl(T func, char* buf, size_t len) +{ + TestClock timer; + uint32_t h = 0; + + timer.start(); + for(int i = 1; i < 1000000 * 100; i++) { + // So the buf is not loop invariant, hence the F(...) + buf[i % 4096] = i; + h += func(buf, len) ^ i; + } + timer.stop(); + + // make h alive + test_printf("%x", h); + return timer.getElapseInSecond(); +} + +struct TestFuncWas +{ + uint32_t operator()(const char* buf, uint32_t len) { + return lj_original_hash(buf, len); + } +}; + +struct TestFuncIs +{ + uint32_t operator()(const char* buf, uint32_t len) { + return lj_str_hash(buf, len); + } +}; + +static void +benchmarkIndividual(char* buf) +{ + fprintf(stdout,"\n\nCompare performance of particular len (in second)\n"); + fprintf(stdout, "%-12s%-8s%-8s%s\n", "len", "was", "is", "diff"); + fprintf(stdout, "-------------------------------------------\n"); + + uint32_t lens[] = {3, 4, 7, 10, 15, 16, 20, 32, 36, 63, 80, 100, + 120, 127, 280, 290, 400}; + for (unsigned i = 0; i < sizeof(lens)/sizeof(lens[0]); i++) { + uint32_t len = lens[i]; + double e1 = BenchmarkHashTmpl(TestFuncWas(), buf, len); + double e2 = BenchmarkHashTmpl(TestFuncIs(), buf, len); + fprintf(stdout, "len = %4d: %-7.3lf %-7.3lf %.2f\n", len, e1, e2, (e1-e2)/e1); + } +} + +template<class T> double +BenchmarkChangeLenTmpl(T func, char* buf, uint32_t* len_vect, uint32_t len_num) +{ + TestClock timer; + uint32_t h = 0; + + timer.start(); + for(int i = 1; i < 1000000 * 100; i++) { + for (int j = 0; j < (int)len_num; j++) { + // So the buf is not loop invariant, hence the F(...) + buf[(i + j) % 4096] = i; + h += func(buf, len_vect[j]) ^ j; + } + } + timer.stop(); + + // make h alive + test_printf("%x", h); + return timer.getElapseInSecond(); +} + +// It is to measure the performance when length is changing. +// The purpose is to see how balanced branches impact the performance. +// +static void +benchmarkToggleLens(char* buf) +{ + double e1, e2; + fprintf(stdout,"\nChanging length (in second):"); + fprintf(stdout, "\n%-20s%-8s%-8s%s\n%s\n", "len", "was", "is", "diff", + separator); + + uint32_t lens1[] = {4, 9}; + e1 = BenchmarkChangeLenTmpl(TestFuncWas(), buf, lens1, 2); + e2 = BenchmarkChangeLenTmpl(TestFuncIs(), buf, lens1, 2); + fprintf(stdout, "%-20s%-7.3lf %-7.3lf %.2f\n", "4,9", e1, e2, (e1-e2)/e1); + + uint32_t lens2[] = {1, 4, 9}; + e1 = BenchmarkChangeLenTmpl(TestFuncWas(), buf, lens2, 3); + e2 = BenchmarkChangeLenTmpl(TestFuncIs(), buf, lens2, 3); + fprintf(stdout, "%-20s%-7.3lf %-7.3lf %.2f\n", "1,4,9", e1, e2, (e1-e2)/e1); + + uint32_t lens3[] = {1, 33, 4, 9}; + e1 = BenchmarkChangeLenTmpl(TestFuncWas(), buf, lens3, 4); + e2 = BenchmarkChangeLenTmpl(TestFuncIs(), buf, lens3, 4); + fprintf(stdout, "%-20s%-7.3lf %-7.3lf %.2f\n", "1,33,4,9", + e1, e2, (e1-e2)/e1); +} + +static void +genRandomString(uint32_t min, uint32_t max, + uint32_t num, vector<string>& result) +{ + double scale = (max - min) / (RAND_MAX + 1.0); + result.clear(); + result.reserve(num); + for (uint32_t i = 0; i < num; i++) { + uint32_t len = (rand() * scale) + min; + + char* buf = new char[len]; + for (uint32_t l = 0; l < len; l++) { + buf[l] = rand() % 255; + } + result.push_back(string(buf, len)); + delete[] buf; + } +} + +// Return the standard deviation of given array of number +static double +standarDeviation(const vector<uint32_t>& v) +{ + uint64_t total = 0; + for (vector<uint32_t>::const_iterator i = v.begin(), e = v.end(); + i != e; ++i) { + total += *i; + } + + double avg = total / (double)v.size(); + double sd = 0; + + for (vector<uint32_t>::const_iterator i = v.begin(), e = v.end(); + i != e; ++i) { + double t = avg - *i; + sd = sd + t*t; + } + + return sqrt(sd/v.size()); +} + +static pair<double, double> +benchmarkConflictHelper(uint32_t bucketNum, const vector<string>& strs) +{ + if (bucketNum & (bucketNum - 1)) { + bucketNum = (1L << (log2_floor(bucketNum) + 1)); + } + uint32_t mask = bucketNum - 1; + + vector<uint32_t> conflictWas(bucketNum); + vector<uint32_t> conflictIs(bucketNum); + + conflictWas.resize(bucketNum); + conflictIs.resize(bucketNum); + + for (vector<string>::const_iterator i = strs.begin(), e = strs.end(); + i != e; ++i) { + uint32_t h1 = lj_original_hash(i->c_str(), i->size()); + uint32_t h2 = lj_str_hash(i->c_str(), i->size()); + + conflictWas[h1 & mask]++; + conflictIs[h2 & mask]++; + } + +#if 0 + std::sort(conflictWas.begin(), conflictWas.end(), std::greater<int>()); + std::sort(conflictIs.begin(), conflictIs.end(), std::greater<int>()); + + fprintf(stderr, "%d %d %d %d vs %d %d %d %d\n", + conflictWas[0], conflictWas[1], conflictWas[2], conflictWas[3], + conflictIs[0], conflictIs[1], conflictIs[2], conflictIs[3]); +#endif + + return pair<double, double>(standarDeviation(conflictWas), + standarDeviation(conflictIs)); +} + +static void +benchmarkConflict() +{ + srand(time(0)); + + float loadFactor[] = { 0.5f, 1.0f, 2.0f, 4.0f, 8.0f }; + int bucketNum[] = { 512, 1024, 2048, 4096, 8192, 16384}; + int lenRange[][2] = { {1,3}, {4, 15}, {16, 127}, {128, 1024}, {1, 1024}}; + + fprintf(stdout, + "\nBechmarking conflict (stand deviation of conflict)\n%s\n", + separator); + + for (uint32_t k = 0; k < sizeof(lenRange)/sizeof(lenRange[0]); k++) { + fprintf(stdout, "\nlen range from %d - %d\n", lenRange[k][0], + lenRange[k][1]); + fprintf(stdout, "%-10s %-12s %-10s %-10s diff\n%s\n", + "bucket", "load-factor", "was", "is", separator); + for (uint32_t i = 0; i < sizeof(bucketNum)/sizeof(bucketNum[0]); ++i) { + for (uint32_t j = 0; + j < sizeof(loadFactor)/sizeof(loadFactor[0]); + ++j) { + int strNum = bucketNum[i] * loadFactor[j]; + vector<string> strs(strNum); + genRandomString(lenRange[k][0], lenRange[k][1], strNum, strs); + + pair<double, double> p; + p = benchmarkConflictHelper(bucketNum[i], strs); + fprintf(stdout, "%-10d %-12.2f %-10.2f %-10.2f %.2f\n", + bucketNum[i], loadFactor[j], p.first, p.second, + p.first - p.second); + } + } + } +} + +static void +benchmarkHashFunc() +{ + char buf[4096]; + char c = getpid() % 'a'; + for (int i = 0; i < (int)sizeof(buf); i++) { + buf[i] = (c + i) % 255; + } + + benchmarkConflict(); + benchmarkIndividual(buf); + benchmarkToggleLens(buf); +} + +int +main(int argc, char** argv) +{ + fprintf(stdout, "========================\nMicro benchmark...\n"); + benchmarkHashFunc(); + return 0; +} diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test.cpp b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test.cpp new file mode 100644 index 0000000..bc92acb --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test.cpp @@ -0,0 +1,73 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <map> +#include "test_util.hpp" +#include "lj_str_hash_x64.h" + +using namespace std; + +static bool +smoke_test() +{ + fprintf(stdout, "running smoke tests...\n"); + char buf[1024]; + char c = getpid() % 'a'; + + for (int i = 0; i < (int)sizeof(buf); i++) { + buf[i] = (c + i) % 255; + } + + uint32_t lens[] = {3, 4, 5, 7, 8, 16, 17, 24, 25, 32, 33, 127, 128, + 255, 256, 257}; + for (unsigned i = 0; i < sizeof(lens)/sizeof(lens[0]); i++) { + string s(buf, lens[i]); + test_printf("%d", lj_str_hash(s.c_str(), lens[i])); + } + + return true; +} + +static bool +verify_log2() +{ + fprintf(stdout, "verify log2...\n"); + bool err = false; + std::map<uint32_t, uint32_t> lm; + lm[0] =(uint32_t)-1; + lm[1] = 0; + lm[2] = 1; + for (int i = 2; i < 31; i++) { + lm[(1<<i) - 2] = i - 1; + lm[(1<<i) - 1] = i - 1; + lm[1<<i] = i; + lm[(1<<i) + 1] = i; + } + lm[(uint32_t)-1] = 31; + + for (map<uint32_t, uint32_t>::iterator iter = lm.begin(), iter_e = lm.end(); + iter != iter_e; ++iter) { + uint32_t v = (*iter).first; + uint32_t log2_expect = (*iter).second; + uint32_t log2_get = log2_floor(v); + if (log2_expect != log2_get) { + err = true; + fprintf(stderr, "log2(%u) expect %u, get %u\n", v, log2_expect, log2_get); + exit(1); + } + } + return !err; +} + +int +main(int argc, char** argv) +{ + fprintf(stdout, "=======================\nRun unit testing...\n"); + + ASSERT(smoke_test(), "smoke_test test failed"); + ASSERT(verify_log2(), "log2 failed"); + + fprintf(stdout, TestErrMsgMgr::noError() ? "succ\n\n" : "fail\n\n"); + + return TestErrMsgMgr::noError() ? 0 : -1; +} diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test_str_comp.lua b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test_str_comp.lua new file mode 100644 index 0000000..3a5c3e6 --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test_str_comp.lua @@ -0,0 +1,67 @@ +--[[ + Given two content-idental string s1, s2, test if they end up to be the + same string object. The purpose of this test is to make sure hash function + do not accidently include extraneous bytes before and after the string in + question. +]] + +local ffi = require("ffi") +local C = ffi.C + +ffi.cdef[[ + void free(void*); + char* malloc(size_t); + void *memset(void*, int, size_t); + void *memcpy(void*, void*, size_t); + long time(void*); + void srandom(unsigned); + long random(void); +]] + + +local function test_equal(len_min, len_max) + -- source string is wrapped by 16-byte-junk both before and after the + -- string + local x = C.random() + local l = len_min + x % (len_max - len_min); + local buf_len = tonumber(l + 16 * 2) + + local src_buf = C.malloc(buf_len) + for i = 0, buf_len - 1 do + src_buf[i] = C.random() % 255 + end + + -- dest string is the clone of the source string, but it is sandwiched + -- by different junk bytes + local dest_buf = C.malloc(buf_len) + C.memset(dest_buf, 0x5a, buf_len) + + local ofst = 8 + (C.random() % 8) + C.memcpy(dest_buf + ofst, src_buf + 16, l); + + local str1 = ffi.string(src_buf + 16, l) + local str2 = ffi.string(dest_buf + ofst, l) + + C.free(src_buf) + C.free(dest_buf) + + if str1 ~= str2 then + -- Oops, look like hash function mistakenly include extraneous bytes + -- close to the string + return 1 -- wtf + end +end + +--local lens = {1, 4, 16, 128, 1024} +local lens = {128, 1024} +local iter = 1000 + +for i = 1, #lens - 1 do + for j = 1, iter do + if test_equal(lens[i], lens[i+1]) ~= nil then + os.exit(1) + end + end +end + +os.exit(0) diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test_util.cxx b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test_util.cxx new file mode 100644 index 0000000..34b7d67 --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test_util.cxx @@ -0,0 +1,21 @@ +#include <stdarg.h> +#include <stdio.h> +#include "test_util.hpp" + +using namespace std; + +std::vector<TestErrMsg> TestErrMsgMgr::_errMsg; + +void +test_printf(const char* format, ...) +{ + va_list args; + va_start (args, format); + + FILE* devNull = fopen("/dev/null", "w"); + if (devNull != 0) { + (void)vfprintf (devNull, format, args); + } + fclose(devNull); + va_end (args); +} diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test_util.hpp b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test_util.hpp new file mode 100644 index 0000000..6cc2ea2 --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/test_util.hpp @@ -0,0 +1,57 @@ +#ifndef _TEST_UTIL_HPP_ +#define _TEST_UTIL_HPP_ + +#include <sys/time.h> // gettimeofday() +#include <string> +#include <vector> + +struct TestErrMsg +{ + const char* fileName; + unsigned lineNo; + std::string errMsg; + + TestErrMsg(const char* FN, unsigned LN, const char* Err): + fileName(FN), lineNo(LN), errMsg(Err) {} +}; + +class TestErrMsgMgr +{ +public: + static std::vector<TestErrMsg> getError(); + static void + addError(const char* fileName, unsigned lineNo, const char* Err) { + _errMsg.push_back(TestErrMsg(fileName, lineNo, Err)); + } + + static bool noError() { + return _errMsg.empty(); + } + +private: + static std::vector<TestErrMsg> _errMsg; +}; + +#define ASSERT(c, e) \ + if (!(c)) { TestErrMsgMgr::addError(__FILE__, __LINE__, (e)); } + +class TestClock +{ +public: + void start() { gettimeofday(&_start, 0); } + void stop() { gettimeofday(&_end, 0); } + double getElapseInSecond() { + return (_end.tv_sec - _start.tv_sec) + + ((long)_end.tv_usec - (long)_start.tv_usec) / 1000000.0; + } + +private: + struct timeval _start, _end; +}; + +// write to /dev/null, the only purpose is to make the data fed to the +// function alive. +extern void test_printf(const char* format, ...) + __attribute__ ((format (printf, 1, 2))); + +#endif //_TEST_UTIL_HPP_ diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_abi.lua b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_abi.lua new file mode 100644 index 0000000..9fafcf5 --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_abi.lua @@ -0,0 +1,10 @@ +local ffi = require "ffi" + +-- TODO: test "gc64" and "win" parameters +assert((ffi.abi("32bit") or ffi.abi("64bit")) + and ffi.abi("le") + and not ffi.abi("be") + and ffi.abi("fpu") + and not ffi.abi("softfp") + and ffi.abi("hardfp") + and not ffi.abi("eabi")) diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_line_directive.lua b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_line_directive.lua new file mode 100644 index 0000000..a8b0403 --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_line_directive.lua @@ -0,0 +1,15 @@ +local x = [=[ +local ffi = require "ffi" + +ffi.cdef [[ + #line 100 + typedef Int xxx +]] +]=] + +local function foo() + loadstring(x)() +end + +local r, e = pcall(foo) +assert(string.find(e, "declaration specifier expected near 'Int' at line 100") ~= nil) diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_pragma_pack_pushpop.lua b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_pragma_pack_pushpop.lua new file mode 100644 index 0000000..5f1bdd3 --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_pragma_pack_pushpop.lua @@ -0,0 +1,12 @@ +local ffi = require "ffi" + +ffi.cdef[[ +#pragma pack(push, 1) +typedef struct { + char x; + double y; +} foo; +#pragma pack(pop) +]] + +assert(ffi.sizeof("foo") == 9) diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_var_attribute.lua b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_var_attribute.lua new file mode 100644 index 0000000..11252bb --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit/ffi/test_var_attribute.lua @@ -0,0 +1,22 @@ +local ffi = require "ffi" + +ffi.cdef[[ +typedef struct { int a; char b; } __attribute__((packed)) myty1; +typedef struct { int a; char b; } __attribute__((__packed__)) myty1_a; + +typedef struct { int a; char b; } __attribute__((aligned(16))) myty2_a; +typedef struct { int a; char b; } __attribute__((__aligned__(16))) myty2; + +typedef int __attribute__ ((vector_size (32))) myty3; +typedef int __attribute__ ((__vector_size__ (32))) myty3_a; + +typedef int __attribute__ ((mode(DI))) myty4; +]] + +assert(ffi.sizeof("myty1") == 5 and + ffi.sizeof("myty1_a") == 5 and + ffi.alignof("myty2") == 16 and + ffi.alignof("myty2_a") == 16 and + ffi.sizeof("myty3") == 32 and + ffi.sizeof("myty3_a") == 32 and + ffi.sizeof("myty4") == 8) diff --git a/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit_test.sh b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit_test.sh new file mode 100644 index 0000000..c6633ca --- /dev/null +++ b/ThirdParty/tolua_runtime/luajit-2.1/src/x64/test/unit_test.sh @@ -0,0 +1,22 @@ +#!/bin/sh +DIR=$(cd $(dirname $0); pwd) +cd $DIR + +LUAJIT=$DIR/../../luajit +HASERR=0 + +find $DIR/unit -name "*.lua" -print | while read x; do + $LUAJIT $x >/dev/null 2>/dev/null + if [ $? -eq 0 ]; then + echo "$x ok" + else + HASERR=1 + echo "$x failed" + fi +done + +if [ $HASERR -eq 0 ]; then + exit 0 +fi + +exit 1 |