TEST(string, __memcmp16) { StringTestState<unsigned short> state(SMALL); for (size_t i = 0; i < state.n; i++) { for (size_t j = 0; j < POS_ITER; j++) { state.NewIteration(); unsigned short mask = 0xffff; unsigned short c1 = rand() & mask; unsigned short c2 = rand() & mask; std::fill(state.ptr1, state.ptr1 + state.MAX_LEN, c1); std::fill(state.ptr2, state.ptr2 + state.MAX_LEN, c1); int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]); state.ptr2[pos] = c2; int expected = (static_cast<unsigned short>(c1) - static_cast<unsigned short>(c2)); int actual = __memcmp16(state.ptr1, state.ptr2, (size_t) state.MAX_LEN); ASSERT_EQ(expected, actual); } } }
/* * public boolean equals(Object anObject) */ bool javaLangString_equals(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) { /* * Null reference check on "this". */ if ((Object*) arg0 == NULL) { dvmThrowNullPointerException(NULL); return false; } /* quick test for comparison with itself */ if (arg0 == arg1) { pResult->i = true; return true; } /* * See if the other object is also a String. * * str.equals(null) is expected to return false, presumably based on * the results of the instanceof test. */ if (arg1 == 0 || ((Object*) arg0)->clazz != ((Object*) arg1)->clazz) { pResult->i = false; return true; } /* * This would be simpler and faster if we promoted StringObject to * a full representation, lining up the C structure fields with the * actual object fields. */ int thisCount, thisOffset, compCount, compOffset; ArrayObject* thisArray; ArrayObject* compArray; const u2* thisChars; const u2* compChars; /* quick length check */ thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT); compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT); if (thisCount != compCount) { pResult->i = false; return true; } /* * You may, at this point, be tempted to pull out the hashCode fields * and compare them. If both fields have been initialized, and they * are not equal, we can return false immediately. * * However, the hashCode field is often not set. If it is set, * there's an excellent chance that the String is being used as a key * in a hashed data structure (e.g. HashMap). That data structure has * already made the comparison and determined that the hashes are equal, * making a check here redundant. * * It's not clear that checking the hashes will be a win in "typical" * use cases. We err on the side of simplicity and ignore them. */ thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET); compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET); thisArray = (ArrayObject*) dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE); compArray = (ArrayObject*) dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE); thisChars = ((const u2*)(void*)thisArray->contents) + thisOffset; compChars = ((const u2*)(void*)compArray->contents) + compOffset; #ifdef HAVE__MEMCMP16 pResult->i = (__memcmp16(thisChars, compChars, thisCount) == 0); # ifdef CHECK_MEMCMP16 int otherRes = (memcmp(thisChars, compChars, thisCount * 2) == 0); if (pResult->i != otherRes) { badMatch((StringObject*) arg0, (StringObject*) arg1, otherRes, pResult->i, "equals-1"); } # endif #else /* * Straightforward implementation, examining 16 bits at a time. The * direction of the loop doesn't matter, and starting at the end may * give us an advantage when comparing certain types of strings (e.g. * class names). * * We want to go forward for benchmarks against __memcmp16 so we get a * meaningful comparison when the strings don't match (could also test * with palindromes). */ int i; //for (i = 0; i < thisCount; i++) for (i = thisCount-1; i >= 0; --i) { if (thisChars[i] != compChars[i]) { pResult->i = false; return true; } } pResult->i = true; #endif return true; }
/* * public int compareTo(String s) */ bool javaLangString_compareTo(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) { /* * Null reference check on "this". Normally this is performed during * the setup of the virtual method call. We need to do it before * anything else. While we're at it, check out the other string, * which must also be non-null. */ if ((Object*) arg0 == NULL || (Object*) arg1 == NULL) { dvmThrowNullPointerException(NULL); return false; } /* quick test for comparison with itself */ if (arg0 == arg1) { pResult->i = 0; return true; } /* * This would be simpler and faster if we promoted StringObject to * a full representation, lining up the C structure fields with the * actual object fields. */ int thisCount, thisOffset, compCount, compOffset; ArrayObject* thisArray; ArrayObject* compArray; const u2* thisChars; const u2* compChars; int minCount, countDiff; thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT); compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT); countDiff = thisCount - compCount; minCount = (countDiff < 0) ? thisCount : compCount; thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET); compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET); thisArray = (ArrayObject*) dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE); compArray = (ArrayObject*) dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE); thisChars = ((const u2*)(void*)thisArray->contents) + thisOffset; compChars = ((const u2*)(void*)compArray->contents) + compOffset; #ifdef HAVE__MEMCMP16 /* * Use assembly version, which returns the difference between the * characters. The annoying part here is that 0x00e9 - 0xffff != 0x00ea, * because the interpreter converts the characters to 32-bit integers * *without* sign extension before it subtracts them (which makes some * sense since "char" is unsigned). So what we get is the result of * 0x000000e9 - 0x0000ffff, which is 0xffff00ea. */ int otherRes = __memcmp16(thisChars, compChars, minCount); # ifdef CHECK_MEMCMP16 int i; for (i = 0; i < minCount; i++) { if (thisChars[i] != compChars[i]) { pResult->i = (s4) thisChars[i] - (s4) compChars[i]; if (pResult->i != otherRes) { badMatch((StringObject*) arg0, (StringObject*) arg1, pResult->i, otherRes, "compareTo"); } return true; } } # endif if (otherRes != 0) { pResult->i = otherRes; return true; } #else /* * Straightforward implementation, examining 16 bits at a time. Compare * the characters that overlap, and if they're all the same then return * the difference in lengths. */ int i; for (i = 0; i < minCount; i++) { if (thisChars[i] != compChars[i]) { pResult->i = (s4) thisChars[i] - (s4) compChars[i]; return true; } } #endif pResult->i = countDiff; return true; }