C backend: avoid generation of deeply nested blocks and long lines (such code is rejected by MSVC).

This commit is contained in:
Alexey Andreev 2018-05-14 22:34:37 +03:00
parent 4d8f33d994
commit d3a9f57c1c
4 changed files with 90 additions and 44 deletions

View File

@ -654,11 +654,14 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
if (statements.isEmpty()) {
return;
}
boolean shouldOptimizeBreaks = !hitsRedundantBreakThreshold(statements, exit);
for (int i = 0; i < statements.size(); ++i) {
Statement stmt = statements.get(i);
if (stmt instanceof ConditionalStatement) {
ConditionalStatement cond = (ConditionalStatement) stmt;
check_conditional: {
check_conditional: if (shouldOptimizeBreaks) {
last = cond.getConsequent().isEmpty() ? null
: cond.getConsequent().get(cond.getConsequent().size() - 1);
if (last instanceof BreakStatement) {
@ -724,6 +727,37 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
}
}
private boolean hitsRedundantBreakThreshold(List<Statement> statements, IdentifiedStatement exit) {
int count = 0;
for (int i = 0; i < statements.size(); ++i) {
Statement stmt = statements.get(i);
if (!(stmt instanceof ConditionalStatement)) {
continue;
}
ConditionalStatement conditional = (ConditionalStatement) stmt;
if (!conditional.getConsequent().isEmpty() && !conditional.getAlternative().isEmpty()) {
continue;
}
List<Statement> innerStatements = !conditional.getConsequent().isEmpty()
? conditional.getConsequent() : conditional.getAlternative();
if (innerStatements.isEmpty()) {
continue;
}
Statement last = innerStatements.get(innerStatements.size() - 1);
if (!(last instanceof BreakStatement)) {
continue;
}
BreakStatement breakStmt = (BreakStatement) last;
if (exit != null && exit == breakStmt.getTarget() && ++count == 8) {
return true;
}
}
return false;
}
private void normalizeConditional(ConditionalStatement stmt) {
if (stmt.getConsequent().isEmpty()) {

View File

@ -56,43 +56,55 @@ public class StringPoolGenerator {
}
private void generateSimpleStringLiteral(String string) {
writer.print("u\"");
for (int j = 0; j < string.length(); ++j) {
char c = string.charAt(j);
switch (c) {
case '\\':
writer.print("\\\\");
break;
case '"':
writer.print("\\\"");
break;
case '\r':
writer.print("\\r");
break;
case '\n':
writer.print("\\n");
break;
case '\t':
writer.print("\\t");
break;
default:
if (c < 32) {
writer.print("\\0" + Character.forDigit(c >> 3, 8) + Character.forDigit(c & 0x7, 8));
} else if (c > 127) {
writer.print("\\u"
+ Character.forDigit(c >> 12, 16)
+ Character.forDigit((c >> 8) & 15, 16)
+ Character.forDigit((c >> 4) & 15, 16)
+ Character.forDigit(c & 15, 16));
} else {
writer.print(String.valueOf(c));
}
break;
}
if (string.isEmpty()) {
writer.print("u\"\"");
return;
}
writer.print("\"");
int chunkSize = 256;
for (int i = 0; i < string.length(); i += chunkSize) {
if (i > 0) {
writer.println();
}
int last = Math.min(i + chunkSize, string.length());
writer.print("u\"");
for (int j = i; j < last; ++j) {
char c = string.charAt(j);
switch (c) {
case '\\':
writer.print("\\\\");
break;
case '"':
writer.print("\\\"");
break;
case '\r':
writer.print("\\r");
break;
case '\n':
writer.print("\\n");
break;
case '\t':
writer.print("\\t");
break;
default:
if (c < 32) {
writer.print("\\0" + Character.forDigit(c >> 3, 8) + Character.forDigit(c & 0x7, 8));
} else if (c > 127) {
writer.print("\\u"
+ Character.forDigit(c >> 12, 16)
+ Character.forDigit((c >> 8) & 15, 16)
+ Character.forDigit((c >> 4) & 15, 16)
+ Character.forDigit(c & 15, 16));
} else {
writer.print(String.valueOf(c));
}
break;
}
}
writer.print("\"");
}
}
private void generateNumericStringLiteral(String string) {

View File

@ -88,7 +88,7 @@ public class RangeTree {
for (Range range : ranges) {
rangeList.add(range);
}
Collections.sort(rangeList, (o1, o2) -> {
rangeList.sort((o1, o2) -> {
if (o1.right != o2.right) {
return o2.right - o1.right;
}

View File

@ -200,13 +200,6 @@ static int64_t currentTimeMillis() {
return time.tv_sec * 1000 + (int64_t) round(time.tv_nsec / 1000000);
}
static int32_t teavm_timeZoneOffset() {
time_t t = time(NULL);
time_t local = mktime(localtime(&t));
time_t utc = mktime(gmtime(&t));
return difftime(utc, local) / 60;
}
#endif
#ifdef _MSC_VER
@ -271,3 +264,10 @@ static int64_t currentTimeMillis() {
return (int64_t) ((current - start) / 10000);
}
#endif
static int32_t teavm_timeZoneOffset() {
time_t t = time(NULL);
time_t local = mktime(localtime(&t));
time_t utc = mktime(gmtime(&t));
return difftime(utc, local) / 60;
}