提交 167230d2 authored 作者: Thomas Mueller's avatar Thomas Mueller

Java to C++ converter

上级 142c2e4b
...@@ -267,9 +267,14 @@ class FieldObj { ...@@ -267,9 +267,14 @@ class FieldObj {
Type type; Type type;
/** /**
* Whether this is a local field. * Whether this is a variable or parameter.
*/ */
boolean isLocal; boolean isVariable;
/**
* Whether this is a local field (not separately garbage collected).
*/
boolean isLocalField;
/** /**
* The field name. * The field name.
......
...@@ -23,21 +23,19 @@ public interface Expr { ...@@ -23,21 +23,19 @@ public interface Expr {
*/ */
class CallExpr implements Expr { class CallExpr implements Expr {
final JavaParser context;
final Expr expr;
final ArrayList<Expr> args = new ArrayList<Expr>(); final ArrayList<Expr> args = new ArrayList<Expr>();
final boolean isStatic; private final JavaParser context;
final String className; private final String className;
final String name; private final String name;
private Expr expr;
private ClassObj classObj; private ClassObj classObj;
private MethodObj method; private MethodObj method;
CallExpr(JavaParser context, Expr expr, String className, String name, boolean isStatic) { CallExpr(JavaParser context, Expr expr, String className, String name) {
this.context = context; this.context = context;
this.expr = expr; this.expr = expr;
this.className = className; this.className = className;
this.name = name; this.name = name;
this.isStatic = isStatic;
} }
private void initMethod() { private void initMethod() {
...@@ -50,6 +48,9 @@ class CallExpr implements Expr { ...@@ -50,6 +48,9 @@ class CallExpr implements Expr {
classObj = expr.getType().classObj; classObj = expr.getType().classObj;
} }
method = classObj.getMethod(name, args); method = classObj.getMethod(name, args);
if (method.isStatic) {
expr = null;
}
} }
public String toString() { public String toString() {
...@@ -165,7 +166,7 @@ class LiteralExpr implements Expr { ...@@ -165,7 +166,7 @@ class LiteralExpr implements Expr {
public String toString() { public String toString() {
if ("null".equals(literal)) { if ("null".equals(literal)) {
return JavaParser.toCType(type) + "()"; return JavaParser.toCType(type, true) + "()";
} }
return literal; return literal;
} }
...@@ -301,7 +302,7 @@ class NewExpr implements Expr { ...@@ -301,7 +302,7 @@ class NewExpr implements Expr {
} }
buff.append("))"); buff.append("))");
} else { } else {
buff.append("new " + JavaParser.toC(classObj.toString())); buff.append("ptr<" + JavaParser.toC(classObj.toString()) + ">(new " + JavaParser.toC(classObj.toString()));
buff.append("("); buff.append("(");
int i = 0; int i = 0;
for (Expr a : args) { for (Expr a : args) {
...@@ -310,7 +311,7 @@ class NewExpr implements Expr { ...@@ -310,7 +311,7 @@ class NewExpr implements Expr {
} }
buff.append(a); buff.append(a);
} }
buff.append(")"); buff.append("))");
} }
return buff.toString(); return buff.toString();
} }
...@@ -458,9 +459,6 @@ class VariableExpr implements Expr { ...@@ -458,9 +459,6 @@ class VariableExpr implements Expr {
private void init() { private void init() {
if (field == null) { if (field == null) {
if (base == null) {
System.out.println("??");
}
Type t = base.getType(); Type t = base.getType();
if (t.arrayLevel > 0) { if (t.arrayLevel > 0) {
if ("length".equals(name)) { if ("length".equals(name)) {
......
...@@ -295,6 +295,7 @@ public class JavaParser { ...@@ -295,6 +295,7 @@ public class JavaParser {
annotations.add(annotation); annotations.add(annotation);
} }
boolean isIgnore = annotations.contains("Ignore"); boolean isIgnore = annotations.contains("Ignore");
boolean isLocalField = annotations.contains("Local");
boolean isStatic = false; boolean isStatic = false;
boolean isFinal = false; boolean isFinal = false;
boolean isPrivate = false; boolean isPrivate = false;
...@@ -369,6 +370,7 @@ public class JavaParser { ...@@ -369,6 +370,7 @@ public class JavaParser {
} else { } else {
FieldObj field = new FieldObj(); FieldObj field = new FieldObj();
field.isIgnore = isIgnore; field.isIgnore = isIgnore;
field.isLocalField = isLocalField;
field.type = type; field.type = type;
field.name = name; field.name = name;
field.isStatic = isStatic; field.isStatic = isStatic;
...@@ -430,7 +432,7 @@ public class JavaParser { ...@@ -430,7 +432,7 @@ public class JavaParser {
private void initThisPointer() { private void initThisPointer() {
thisPointer = new FieldObj(); thisPointer = new FieldObj();
thisPointer.isLocal = true; thisPointer.isVariable = true;
thisPointer.name = "this"; thisPointer.name = "this";
thisPointer.type = new Type(); thisPointer.type = new Type();
thisPointer.type.classObj = classObj; thisPointer.type.classObj = classObj;
...@@ -456,7 +458,7 @@ public class JavaParser { ...@@ -456,7 +458,7 @@ public class JavaParser {
} }
while (true) { while (true) {
FieldObj field = new FieldObj(); FieldObj field = new FieldObj();
field.isLocal = true; field.isVariable = true;
String typeName = readTypeOrIdentifier(); String typeName = readTypeOrIdentifier();
field.type = readType(typeName); field.type = readType(typeName);
if (field.type.isVarArgs) { if (field.type.isVarArgs) {
...@@ -593,7 +595,7 @@ public class JavaParser { ...@@ -593,7 +595,7 @@ public class JavaParser {
FieldObj f = new FieldObj(); FieldObj f = new FieldObj();
f.name = name; f.name = name;
f.type = type; f.type = type;
f.isLocal = true; f.isVariable = true;
localVars.put(name, f); localVars.put(name, f);
read(":"); read(":");
forStat.iterableType = type; forStat.iterableType = type;
...@@ -646,7 +648,7 @@ public class JavaParser { ...@@ -646,7 +648,7 @@ public class JavaParser {
} }
} }
FieldObj f = new FieldObj(); FieldObj f = new FieldObj();
f.isLocal = true; f.isVariable = true;
f.type = dec.type; f.type = dec.type;
f.name = varName; f.name = varName;
localVars.put(varName, f); localVars.put(varName, f);
...@@ -706,12 +708,163 @@ public class JavaParser { ...@@ -706,12 +708,163 @@ public class JavaParser {
} }
private Expr readExpr2() { private Expr readExpr2() {
Expr expr = readExpr2a();
while (true) {
String infixOp = current.token;
if (readIf("||")) {
OpExpr opExpr = new OpExpr(this);
opExpr.left = expr;
opExpr.op = infixOp;
opExpr.right = readExpr2a();
expr = opExpr;
} else {
break;
}
}
return expr;
}
private Expr readExpr2a() {
Expr expr = readExpr2b();
while (true) {
String infixOp = current.token;
if (readIf("&&")) {
OpExpr opExpr = new OpExpr(this);
opExpr.left = expr;
opExpr.op = infixOp;
opExpr.right = readExpr2b();
expr = opExpr;
} else {
break;
}
}
return expr;
}
private Expr readExpr2b() {
Expr expr = readExpr2c();
while (true) {
String infixOp = current.token;
if (readIf("|")) {
OpExpr opExpr = new OpExpr(this);
opExpr.left = expr;
opExpr.op = infixOp;
opExpr.right = readExpr2c();
expr = opExpr;
} else {
break;
}
}
return expr;
}
private Expr readExpr2c() {
Expr expr = readExpr2d();
while (true) {
String infixOp = current.token;
if (readIf("^")) {
OpExpr opExpr = new OpExpr(this);
opExpr.left = expr;
opExpr.op = infixOp;
opExpr.right = readExpr2d();
expr = opExpr;
} else {
break;
}
}
return expr;
}
private Expr readExpr2d() {
Expr expr = readExpr2e();
while (true) {
String infixOp = current.token;
if (readIf("&")) {
OpExpr opExpr = new OpExpr(this);
opExpr.left = expr;
opExpr.op = infixOp;
opExpr.right = readExpr2e();
expr = opExpr;
} else {
break;
}
}
return expr;
}
private Expr readExpr2e() {
Expr expr = readExpr2f();
while (true) {
String infixOp = current.token;
if (readIf("==") || readIf("!=")) {
OpExpr opExpr = new OpExpr(this);
opExpr.left = expr;
opExpr.op = infixOp;
opExpr.right = readExpr2f();
expr = opExpr;
} else {
break;
}
}
return expr;
}
private Expr readExpr2f() {
Expr expr = readExpr2g();
while (true) {
String infixOp = current.token;
if (readIf("<") || readIf(">") || readIf("<=") || readIf(">=")) {
OpExpr opExpr = new OpExpr(this);
opExpr.left = expr;
opExpr.op = infixOp;
opExpr.right = readExpr2g();
expr = opExpr;
} else {
break;
}
}
return expr;
}
private Expr readExpr2g() {
Expr expr = readExpr2h();
while (true) {
String infixOp = current.token;
if (readIf("<<") || readIf(">>") || readIf(">>>")) {
OpExpr opExpr = new OpExpr(this);
opExpr.left = expr;
opExpr.op = infixOp;
opExpr.right = readExpr2h();
expr = opExpr;
} else {
break;
}
}
return expr;
}
private Expr readExpr2h() {
Expr expr = readExpr2i();
while (true) {
String infixOp = current.token;
if (readIf("+") || readIf("-")) {
OpExpr opExpr = new OpExpr(this);
opExpr.left = expr;
opExpr.op = infixOp;
opExpr.right = readExpr2i();
expr = opExpr;
} else {
break;
}
}
return expr;
}
private Expr readExpr2i() {
Expr expr = readExpr3(); Expr expr = readExpr3();
while (true) { while (true) {
String infixOp = current.token; String infixOp = current.token;
if (readIf("||") || readIf("&&") || readIf("|") || readIf("^") || readIf("&") || readIf("==") || readIf("!=") if (readIf("*") || readIf("/") || readIf("%")) {
|| readIf("<") || readIf(">") || readIf("<=") || readIf(">=") || readIf("<<") || readIf(">>")
|| readIf(">>>") || readIf("+") || readIf("-") || readIf("*") || readIf("/") || readIf("%")) {
OpExpr opExpr = new OpExpr(this); OpExpr opExpr = new OpExpr(this);
opExpr.left = expr; opExpr.left = expr;
opExpr.op = infixOp; opExpr.op = infixOp;
...@@ -798,7 +951,7 @@ public class JavaParser { ...@@ -798,7 +951,7 @@ public class JavaParser {
if (readIf(".")) { if (readIf(".")) {
String n = readIdentifier(); String n = readIdentifier();
if (readIf("(")) { if (readIf("(")) {
CallExpr e2 = new CallExpr(this, expr, null, n, false); CallExpr e2 = new CallExpr(this, expr, null, n);
if (!readIf(")")) { if (!readIf(")")) {
while (true) { while (true) {
e2.args.add(readExpr()); e2.args.add(readExpr());
...@@ -894,17 +1047,24 @@ public class JavaParser { ...@@ -894,17 +1047,24 @@ public class JavaParser {
} }
if (readIf("this")) { if (readIf("this")) {
VariableExpr expr = new VariableExpr(this); VariableExpr expr = new VariableExpr(this);
expr.field = thisPointer;
if (thisPointer == null) { if (thisPointer == null) {
throw getSyntaxException("'this' used in a static context"); throw getSyntaxException("'this' used in a static context");
} }
expr.field = thisPointer;
return expr; return expr;
} }
String name = readIdentifier(); String name = readIdentifier();
if (readIf("(")) { if (readIf("(")) {
VariableExpr t = new VariableExpr(this); VariableExpr t;
t.field = thisPointer; if (thisPointer == null) {
CallExpr expr = new CallExpr(this, t, classObj.className, name, false); // static method calling another static method
t = null;
} else {
// non-static method calling a static or non-static method
t = new VariableExpr(this);
t.field = thisPointer;
}
CallExpr expr = new CallExpr(this, t, classObj.className, name);
if (!readIf(")")) { if (!readIf(")")) {
while (true) { while (true) {
expr.args.add(readExpr()); expr.args.add(readExpr());
...@@ -937,7 +1097,7 @@ public class JavaParser { ...@@ -937,7 +1097,7 @@ public class JavaParser {
if (readIf(".")) { if (readIf(".")) {
String n = readIdentifier(); String n = readIdentifier();
if (readIf("(")) { if (readIf("(")) {
CallExpr e2 = new CallExpr(this, null, imp, n, true); CallExpr e2 = new CallExpr(this, null, imp, n);
if (!readIf(")")) { if (!readIf(")")) {
while (true) { while (true) {
e2.args.add(readExpr()); e2.args.add(readExpr());
...@@ -961,7 +1121,7 @@ public class JavaParser { ...@@ -961,7 +1121,7 @@ public class JavaParser {
} }
} }
expr.field = f; expr.field = f;
if (f != null && (!f.isLocal && !f.isStatic)) { if (f != null && (!f.isVariable && !f.isStatic)) {
VariableExpr ve = new VariableExpr(this); VariableExpr ve = new VariableExpr(this);
ve.field = thisPointer; ve.field = thisPointer;
expr.base = ve; expr.base = ve;
...@@ -1391,7 +1551,6 @@ public class JavaParser { ...@@ -1391,7 +1551,6 @@ public class JavaParser {
out.println(s); out.println(s);
} }
out.println(); out.println();
// two classes, similar to the pimpl idiom
for (ClassObj c : classes.values()) { for (ClassObj c : classes.values()) {
out.println("class " + toC(c.className) + ";"); out.println("class " + toC(c.className) + ";");
} }
...@@ -1402,7 +1561,7 @@ public class JavaParser { ...@@ -1402,7 +1561,7 @@ public class JavaParser {
if (f.isFinal) { if (f.isFinal) {
buff.append("const "); buff.append("const ");
} }
buff.append(toCType(f.type)); buff.append(toCType(f.type, !f.isLocalField));
buff.append(" ").append(toC(c.className + "." + f.name)); buff.append(" ").append(toC(c.className + "." + f.name));
buff.append(";"); buff.append(";");
out.println(buff.toString()); out.println(buff.toString());
...@@ -1413,14 +1572,14 @@ public class JavaParser { ...@@ -1413,14 +1572,14 @@ public class JavaParser {
continue; continue;
} }
if (m.isStatic) { if (m.isStatic) {
out.print(toCType(m.returnType)); out.print(toCType(m.returnType, true));
out.print(" " + toC(c.className + "_" + m.name) + "("); out.print(" " + toC(c.className + "_" + m.name) + "(");
int i = 0; int i = 0;
for (FieldObj p : m.parameters.values()) { for (FieldObj p : m.parameters.values()) {
if (i > 0) { if (i > 0) {
out.print(", "); out.print(", ");
} }
out.print(toCType(p.type) + " " + p.name); out.print(toCType(p.type, false) + " " + p.name);
i++; i++;
} }
out.println(");"); out.println(");");
...@@ -1441,7 +1600,7 @@ public class JavaParser { ...@@ -1441,7 +1600,7 @@ public class JavaParser {
out.println("public:"); out.println("public:");
for (FieldObj f : c.instanceFields.values()) { for (FieldObj f : c.instanceFields.values()) {
out.print(" "); out.print(" ");
out.print(toCType(f.type) + " " + f.name); out.print(toCType(f.type, !f.isLocalField) + " " + f.name);
if (f.value != null) { if (f.value != null) {
out.print(" = " + f.value); out.print(" = " + f.value);
} }
...@@ -1459,14 +1618,14 @@ public class JavaParser { ...@@ -1459,14 +1618,14 @@ public class JavaParser {
if (m.isConstructor) { if (m.isConstructor) {
out.print(" " + toC(c.className) + "("); out.print(" " + toC(c.className) + "(");
} else { } else {
out.print(" " + toCType(m.returnType) + " " + m.name + "("); out.print(" " + toCType(m.returnType, true) + " " + m.name + "(");
} }
int i = 0; int i = 0;
for (FieldObj p : m.parameters.values()) { for (FieldObj p : m.parameters.values()) {
if (i > 0) { if (i > 0) {
out.print(", "); out.print(", ");
} }
out.print(toCType(p.type)); out.print(toCType(p.type, false));
out.print(" " + p.name); out.print(" " + p.name);
i++; i++;
} }
...@@ -1499,7 +1658,7 @@ public class JavaParser { ...@@ -1499,7 +1658,7 @@ public class JavaParser {
if (f.isFinal) { if (f.isFinal) {
buff.append("const "); buff.append("const ");
} }
buff.append(toCType(f.type)); buff.append(toCType(f.type, !f.isLocalField));
buff.append(" ").append(toC(c.className + "." + f.name)); buff.append(" ").append(toC(c.className + "." + f.name));
if (f.value != null) { if (f.value != null) {
buff.append(" = " + f.value); buff.append(" = " + f.value);
...@@ -1513,18 +1672,18 @@ public class JavaParser { ...@@ -1513,18 +1672,18 @@ public class JavaParser {
continue; continue;
} }
if (m.isStatic) { if (m.isStatic) {
out.print(toCType(m.returnType) + " " + toC(c.className + "_" + m.name) + "("); out.print(toCType(m.returnType, true) + " " + toC(c.className + "_" + m.name) + "(");
} else if (m.isConstructor) { } else if (m.isConstructor) {
out.print(toC(c.className) + "::" + toC(c.className) + "("); out.print(toC(c.className) + "::" + toC(c.className) + "(");
} else { } else {
out.print(toCType(m.returnType) + " " + toC(c.className) + "::" + m.name + "("); out.print(toCType(m.returnType, true) + " " + toC(c.className) + "::" + m.name + "(");
} }
int i = 0; int i = 0;
for (FieldObj p : m.parameters.values()) { for (FieldObj p : m.parameters.values()) {
if (i > 0) { if (i > 0) {
out.print(", "); out.print(", ");
} }
out.print(toCType(p.type) + " " + p.name); out.print(toCType(p.type, false) + " " + p.name);
i++; i++;
} }
out.println(") {"); out.println(") {");
...@@ -1578,18 +1737,35 @@ public class JavaParser { ...@@ -1578,18 +1737,35 @@ public class JavaParser {
return identifier.replace('.', '_'); return identifier.replace('.', '_');
} }
static String toCType(Type type) { static String toCType(Type type, boolean refCounted) {
// TODO not everything needs to be ref-counted
refCounted = true;
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
for (int i = 0; i < type.arrayLevel; i++) { for (int i = 0; i < type.arrayLevel; i++) {
buff.append("ptr<array< "); if (refCounted) {
buff.append("ptr<array< ");
} else {
buff.append("array< ");
}
} }
if (type.classObj.isPrimitive) { if (type.classObj.isPrimitive) {
buff.append(toC(type.classObj.toString())); buff.append(toC(type.classObj.toString()));
} else { } else {
buff.append("ptr<").append(toC(type.classObj.toString())).append('>'); if (refCounted) {
buff.append("ptr<").append(toC(type.classObj.toString())).append('>');
} else {
buff.append(toC(type.classObj.toString()));
}
} }
for (int i = 0; i < type.arrayLevel; i++) { for (int i = 0; i < type.arrayLevel; i++) {
buff.append(" > >"); if (refCounted) {
buff.append(" > >");
} else {
buff.append(" >");
}
}
if (!refCounted) {
buff.append("*");
} }
return buff.toString(); return buff.toString();
} }
......
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.java;
/**
* This annotation marks fields that are not shared and therefore don't need to
* be garbage collected separately.
*/
public @interface Local {
// empty
}
...@@ -44,7 +44,7 @@ class ReturnStatement extends StatementBase { ...@@ -44,7 +44,7 @@ class ReturnStatement extends StatementBase {
if (expr.getType().isSimplePrimitive()) { if (expr.getType().isSimplePrimitive()) {
return "return " + expr + ";"; return "return " + expr + ";";
} }
return "return " + JavaParser.toCType(expr.getType()) + "(" + expr + ");"; return "return " + JavaParser.toCType(expr.getType(), true) + "(" + expr + ");";
} }
} }
...@@ -253,7 +253,7 @@ class VarDecStatement extends StatementBase { ...@@ -253,7 +253,7 @@ class VarDecStatement extends StatementBase {
public String toString() { public String toString() {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append(JavaParser.toCType(type)).append(' '); buff.append(JavaParser.toCType(type, true)).append(' ');
StringBuilder assign = new StringBuilder(); StringBuilder assign = new StringBuilder();
for (int i = 0; i < variables.size(); i++) { for (int i = 0; i < variables.size(); i++) {
if (i > 0) { if (i > 0) {
......
...@@ -30,13 +30,16 @@ public class Test extends TestBase { ...@@ -30,13 +30,16 @@ public class Test extends TestBase {
// chmod +x test // chmod +x test
// ./test // ./test
// (for "mixed declarations and code") // include files:
// /usr/include/c++/4.2.1/tr1/stdio.h
// /usr/include/stdio.h
// TODO initialize fields
// not supported yet: // not supported yet:
// exceptions // exceptions
// HexadecimalFloatingPointLiteral // HexadecimalFloatingPointLiteral
// int x()[] { return null; } // int x()[] { return null; }
// annotations
// import static // import static
// import * // import *
// initializer blocks // initializer blocks
...@@ -66,6 +69,7 @@ public class Test extends TestBase { ...@@ -66,6 +69,7 @@ public class Test extends TestBase {
parser.parse("src/tools/org/h2", "java.lang.String"); parser.parse("src/tools/org/h2", "java.lang.String");
parser.parse("src/tools/org/h2", "java.lang.Math"); parser.parse("src/tools/org/h2", "java.lang.Math");
parser.parse("src/tools/org/h2", "java.lang.Integer"); parser.parse("src/tools/org/h2", "java.lang.Integer");
parser.parse("src/tools/org/h2", "java.lang.Long");
parser.parse("src/tools/org/h2", "java.lang.StringBuilder"); parser.parse("src/tools/org/h2", "java.lang.StringBuilder");
parser.parse("src/tools/org/h2", "java.io.PrintStream"); parser.parse("src/tools/org/h2", "java.io.PrintStream");
parser.parse("src/tools/org/h2", "java.lang.System"); parser.parse("src/tools/org/h2", "java.lang.System");
......
/*
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.java.lang;
/**
* A java.lang.Long implementation.
*/
public class Long {
public static final long MIN_VALUE = 1L << 63;
public static final long MAX_VALUE = (1L << 63) - 1;
/**
* Convert a value to a String.
*
* @param x the value
* @return the String
*/
public static String toString(long x) {
// c: wchar_t ch[30];
// c: swprintf(ch, 30, L"%ld", x);
// c: return STRING(ch);
// c: return;
if (x == MIN_VALUE) {
return String.wrap("-9223372036854775808");
}
char[] ch = new char[30];
int i = 30 - 1, count = 0;
boolean negative;
if (x < 0) {
negative = true;
x = -x;
} else {
negative = false;
}
for (; i >= 0; i--) {
ch[i] = (char) ('0' + (x % 10));
x /= 10;
count++;
if (x == 0) {
break;
}
}
if (negative) {
ch[--i] = '-';
count++;
}
return new String(ch, i, count);
}
}
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package org.h2.java.lang; package org.h2.java.lang;
import org.h2.java.Ignore; import org.h2.java.Ignore;
import org.h2.java.Local;
/* c: /* c:
...@@ -37,7 +38,7 @@ protected: ...@@ -37,7 +38,7 @@ protected:
jint refCount; jint refCount;
public: public:
RefBase() { RefBase() {
refCount = 1; refCount = 0;
} }
void reference() { void reference() {
refCount++; refCount++;
...@@ -47,6 +48,8 @@ public: ...@@ -47,6 +48,8 @@ public:
delete this; delete this;
} }
} }
virtual ~RefBase() {
}
}; };
template <class T> class ptr { template <class T> class ptr {
T* pointer; T* pointer;
...@@ -137,6 +140,7 @@ public class String { ...@@ -137,6 +140,7 @@ public class String {
/** /**
* The character array. * The character array.
*/ */
@Local
char[] chars; char[] chars;
private int hash; private int hash;
...@@ -152,18 +156,17 @@ public class String { ...@@ -152,18 +156,17 @@ public class String {
} }
public int hashCode() { public int hashCode() {
if (hash == 0) { int h = hash;
if (chars.length == 0) { if (h == 0) {
return 0; int size = chars.length;
} if (size != 0) {
int h = 0; for (int i = 0; i < size; i++) {
for (char c : chars) { h = h * 31 + chars[i];
h = h * 31 + c; }
hash = h;
} }
hash = h;
return h;
} }
return hash; return h;
} }
/** /**
......
...@@ -56,4 +56,21 @@ public class System { ...@@ -56,4 +56,21 @@ public class System {
java.lang.System.arraycopy(src, srcPos, dest, destPos, length); java.lang.System.arraycopy(src, srcPos, dest, destPos, length);
} }
/**
* Get the current time in milliseconds since 1970-01-01.
*
* @return the milliseconds
*/
public static long nanoTime() {
/* c:
#if CLOCKS_PER_SEC == 1000000
return (jlong) clock() * 1000;
#else
return (jlong) clock() * 1000000 / CLOCKS_PER_SEC;
#endif
*/
// c: return;
return java.lang.System.nanoTime();
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论