Skip to content

Commit d642efa

Browse files
Invoke javac once to optimize compliation time (#777)
* perf: compile all Java files using javac at once * refactor: resolve a cppcheck warning * fix: the process removing class files * fix: do not compile unnecessary Java files * fix: compiler warnings * fix: cppcheck warnings * change: set PROGRAM_ID_LIST_MAX_LEN to 65536(=2^16) * add: the file number check * fix: increase buffer size * refactor: simplify cobj.c
1 parent e4907f9 commit d642efa

1 file changed

Lines changed: 97 additions & 81 deletions

File tree

cobj/cobj.c

Lines changed: 97 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,9 @@ char *cb_single_jar_name = NULL;
198198
int cb_flag_info_json = 0;
199199
char *cb_info_json_dir = NULL;
200200

201-
#define PROGRAM_ID_LIST_MAX_LEN 1024
201+
#define PROGRAM_ID_LIST_MAX_LEN (65536)
202202
char *program_id_list[PROGRAM_ID_LIST_MAX_LEN];
203+
int program_id_list_index = 0;
203204

204205
#ifdef _MSC_VER
205206
#if _MSC_VER >= 1400
@@ -1822,10 +1823,7 @@ static int process_translate(struct filename *fn) {
18221823
}
18231824

18241825
/* translate to Java */
1825-
for (i = 0; i < PROGRAM_ID_LIST_MAX_LEN; ++i) {
1826-
program_id_list[i] = NULL;
1827-
}
1828-
codegen(p, 0, program_id_list,
1826+
codegen(p, 0, &program_id_list[program_id_list_index++],
18291827
java_source_dir == NULL ? (char *)"./" : java_source_dir, fn->source);
18301828

18311829
return 0;
@@ -1843,104 +1841,106 @@ static void package_name_to_path(char *buff, char *package_name) {
18431841
}
18441842
}
18451843

1846-
static int process_compile(struct filename *fn) {
1847-
char buff[COB_MEDIUM_BUFF];
1844+
static int process_compile_all(void) {
1845+
#define BUFF_SIZE (COB_LARGE_BUFF * 32)
1846+
char buff[BUFF_SIZE];
18481847
char buff2[COB_SMALL_BUFF];
1849-
char name[COB_MEDIUM_BUFF];
18501848
int ret = 0;
18511849
#ifdef _WIN32
18521850
char current_dir[] = ".\\";
1853-
char remove_cmd[] = "del";
18541851
#else
18551852
char current_dir[] = "./";
1856-
char remove_cmd[] = "rm -rf";
18571853
#endif
18581854

1859-
if (output_name) {
1860-
strcpy(name, output_name);
1861-
} else {
1862-
file_basename(fn->source, name);
1863-
}
1864-
18651855
char *output_name_a = output_name == NULL ? current_dir : output_name;
18661856
char *java_source_dir_a =
18671857
java_source_dir == NULL ? current_dir : java_source_dir;
18681858

1859+
/* Build list of Java files to compile */
1860+
/* Reserve space for "javac ... -encoding ... -d ... " prefix (at least 1024
1861+
* bytes) */
1862+
#define JAVA_FILES_MAX_LEN (BUFF_SIZE / 2)
1863+
char java_files[JAVA_FILES_MAX_LEN] = "";
18691864
char **program_id;
18701865
for (program_id = program_id_list; *program_id; ++program_id) {
1871-
snprintf(buff, COB_MEDIUM_BUFF, "javac %s -encoding %s -d %s %s/%s.java",
1872-
cob_java_flags, JAVAC_ENCODING, output_name_a, java_source_dir_a,
1873-
*program_id);
1874-
ret = process(buff);
1866+
if (strlen(java_files) + strlen(java_source_dir_a) + strlen(*program_id) +
1867+
10 >
1868+
JAVA_FILES_MAX_LEN) {
1869+
fprintf(stderr, "Too many Java files to compile at once\n");
1870+
return -1;
1871+
}
1872+
strcat(java_files, java_source_dir_a);
1873+
strcat(java_files, "/");
1874+
strcat(java_files, *program_id);
1875+
strcat(java_files, ".java ");
1876+
}
1877+
#undef JAVA_FILES_MAX_LEN
18751878

1876-
if (ret) {
1877-
return ret;
1879+
/* Compile all Java files at once */
1880+
snprintf(buff, BUFF_SIZE, "javac %s -encoding %s -d %s %s", cob_java_flags,
1881+
JAVAC_ENCODING, output_name_a, java_files);
1882+
ret = process(buff);
1883+
if (ret) {
1884+
return ret;
1885+
}
1886+
1887+
/* Create jar files if cb_flag_jar is set */
1888+
if (cb_flag_jar) {
1889+
char *package_dir;
1890+
if (cb_java_package_name) {
1891+
package_name_to_path(buff2, cb_java_package_name);
1892+
package_dir = buff2;
1893+
} else {
1894+
package_dir = (char *)".";
18781895
}
1879-
if (cb_flag_jar) {
1880-
char *package_dir;
1881-
if (cb_java_package_name) {
1882-
package_name_to_path(buff2, cb_java_package_name);
1883-
package_dir = buff2;
1884-
} else {
1885-
package_dir = (char *)".";
1886-
}
1887-
snprintf(buff, COB_MEDIUM_BUFF,
1888-
"cd %s && jar --create --main-class=%s --file=%s.jar %s/*.class",
1889-
output_name_a, *program_id, *program_id, package_dir);
1896+
1897+
for (program_id = program_id_list; *program_id; ++program_id) {
1898+
snprintf(buff, BUFF_SIZE,
1899+
"cd %s && jar --create --main-class=%s --file=%s.jar "
1900+
"%s%c%s.class %s%c%s$*.class",
1901+
output_name_a, *program_id, *program_id, package_dir,
1902+
file_path_delimitor, *program_id, package_dir,
1903+
file_path_delimitor, *program_id);
18901904
ret = process(buff);
18911905
if (ret) {
18921906
return ret;
18931907
}
1894-
snprintf(buff, COB_MEDIUM_BUFF, "%s %s%c%s.class %s%c%s$*.class",
1895-
remove_cmd, output_name_a, file_path_delimitor, *program_id,
1896-
output_name_a, file_path_delimitor, *program_id);
1908+
#ifdef _WIN32
1909+
char remove_cmd[] = "del";
1910+
#else
1911+
char remove_cmd[] = "rm";
1912+
#endif
1913+
snprintf(buff, BUFF_SIZE, "%s %s%c%s%c%s.class %s%c%s%c%s$*.class",
1914+
remove_cmd, output_name_a, file_path_delimitor, package_dir,
1915+
file_path_delimitor, *program_id, output_name_a,
1916+
file_path_delimitor, package_dir, file_path_delimitor,
1917+
*program_id);
18971918
process(buff);
18981919
}
18991920
}
1921+
#undef BUFF_SIZE
19001922
return ret;
19011923
}
19021924

1903-
static int process_build_module(struct filename *fn) {
1925+
static int process_build_module_all(void) {
19041926
int ret = 0;
19051927
char buff[COB_MEDIUM_BUFF];
1906-
char name[COB_MEDIUM_BUFF];
1907-
1908-
char basename[COB_MEDIUM_BUFF];
1909-
file_basename(fn->source, basename);
1910-
struct cb_program *p;
19111928
#ifdef _WIN32
19121929
char remove_cmd[] = "del";
19131930
#else
19141931
char remove_cmd[] = "rm";
19151932
#endif
19161933

1917-
if (output_name) {
1918-
strcpy(name, output_name);
1919-
#if defined(_MSC_VER)
1920-
file_stripext(name);
1921-
#else
1922-
if (strchr(output_name, '.') == NULL) {
1923-
strcat(name, ".");
1924-
strcat(name, COB_MODULE_EXT);
1925-
}
1926-
#endif
1927-
} else {
1928-
file_basename(fn->source, name);
1929-
#if !defined(_MSC_VER)
1930-
strcat(name, ".");
1931-
strcat(name, COB_MODULE_EXT);
1932-
#endif
1933-
}
1934-
1935-
for (p = current_program; p; p = p->next_program) {
1936-
sprintf(buff, "jar cf %s.jar ./%s.class ./%s$*.class", p->program_id,
1937-
p->program_id, p->program_id);
1934+
char **program_id;
1935+
for (program_id = program_id_list; *program_id; ++program_id) {
1936+
sprintf(buff, "jar cf %s.jar ./%s.class ./%s$*.class", *program_id,
1937+
*program_id, *program_id);
19381938
ret = process(buff);
19391939
if (ret) {
19401940
return ret;
19411941
}
1942-
sprintf(buff, "%s %s.class %s$*.class", remove_cmd, p->program_id,
1943-
p->program_id);
1942+
sprintf(buff, "%s %s.class %s$*.class", remove_cmd, *program_id,
1943+
*program_id);
19441944
ret = process(buff);
19451945
if (ret) {
19461946
return ret;
@@ -2374,6 +2374,13 @@ int main(int argc, char *argv[]) {
23742374
cb_pretty_display = 0;
23752375
}
23762376

2377+
/* Check if the number of COBOL programs exceeds the limit */
2378+
if (argc - iargs > PROGRAM_ID_LIST_MAX_LEN) {
2379+
fprintf(stderr, "Error: Too many COBOL programs (max %d)\n",
2380+
PROGRAM_ID_LIST_MAX_LEN);
2381+
exit(1);
2382+
}
2383+
23772384
while (iargs < argc) {
23782385
fn = process_filename(argv[iargs++]);
23792386
if (!fn) {
@@ -2389,6 +2396,13 @@ int main(int argc, char *argv[]) {
23892396
}
23902397
}
23912398
}
2399+
2400+
/* Initialize program_id_list before translation loop */
2401+
program_id_list_index = 0;
2402+
for (int i = 0; i < PROGRAM_ID_LIST_MAX_LEN; ++i) {
2403+
program_id_list[i] = NULL;
2404+
}
2405+
23922406
for (fn = file_list; fn; fn = fn->next) {
23932407
cb_id = 1;
23942408
cb_attr_id = 1;
@@ -2434,24 +2448,26 @@ int main(int argc, char *argv[]) {
24342448
continue;
24352449
}
24362450

2437-
/* Compile */
2438-
if (!cb_single_jar_name && (cb_compile_level == CB_LEVEL_COMPILE ||
2439-
cb_compile_level == CB_LEVEL_MODULE)) {
2440-
if (process_compile(fn) != 0) {
2441-
cobc_clean_up(status);
2442-
return status;
2443-
}
2451+
/* Build executable */
2452+
if (cb_compile_level == CB_LEVEL_EXECUTABLE) {
2453+
fprintf(stderr, "Building executable files is not supported");
24442454
}
2455+
}
24452456

2446-
/* Build module */
2447-
if (cb_compile_level == CB_LEVEL_MODULE) {
2448-
if (process_build_module(fn) != 0) {
2449-
cobc_clean_up(status);
2450-
return status;
2451-
}
2452-
/* Build executable */
2453-
} else if (cb_compile_level == CB_LEVEL_EXECUTABLE) {
2454-
fprintf(stderr, "Building executable files is not supported");
2457+
/* Compile all Java files at once after all translations are complete */
2458+
if (!cb_single_jar_name && (cb_compile_level == CB_LEVEL_COMPILE ||
2459+
cb_compile_level == CB_LEVEL_MODULE)) {
2460+
if (process_compile_all() != 0) {
2461+
cobc_clean_up(status);
2462+
return status;
2463+
}
2464+
}
2465+
2466+
/* Build module for all programs */
2467+
if (cb_compile_level == CB_LEVEL_MODULE) {
2468+
if (process_build_module_all() != 0) {
2469+
cobc_clean_up(status);
2470+
return status;
24552471
}
24562472
}
24572473

0 commit comments

Comments
 (0)