Add an arm32 port of nterp.
Currently using arm32, will try thumb once this CL lands to compare
performance.
Test: test.py, run-libcore-tests, device boots
Bug: 112676029
Change-Id: I6535e2982a3ceed83eba6664fc8ba8609974bc08
diff --git a/runtime/interpreter/mterp/nterp.cc b/runtime/interpreter/mterp/nterp.cc
index 74e49e7..3d92473 100644
--- a/runtime/interpreter/mterp/nterp.cc
+++ b/runtime/interpreter/mterp/nterp.cc
@@ -118,6 +118,111 @@
UpdateCache(self, dex_pc_ptr, reinterpret_cast<size_t>(value));
}
+#ifdef __arm__
+
+extern "C" void NterpStoreArm32Fprs(const char* shorty,
+ uint32_t* registers,
+ uint32_t* stack_args,
+ const uint32_t* fprs) {
+ // Note `shorty` has already the returned type removed.
+ ScopedAssertNoThreadSuspension sants("In nterp");
+ uint32_t arg_index = 0;
+ uint32_t fpr_double_index = 0;
+ uint32_t fpr_index = 0;
+ for (uint32_t shorty_index = 0; shorty[shorty_index] != '\0'; ++shorty_index) {
+ char arg_type = shorty[shorty_index];
+ switch (arg_type) {
+ case 'D': {
+ // Double should not overlap with float.
+ fpr_double_index = std::max(fpr_double_index, RoundUp(fpr_index, 2));
+ if (fpr_double_index < 16) {
+ registers[arg_index] = fprs[fpr_double_index++];
+ registers[arg_index + 1] = fprs[fpr_double_index++];
+ } else {
+ registers[arg_index] = stack_args[arg_index];
+ registers[arg_index + 1] = stack_args[arg_index + 1];
+ }
+ arg_index += 2;
+ break;
+ }
+ case 'F': {
+ if (fpr_index % 2 == 0) {
+ fpr_index = std::max(fpr_double_index, fpr_index);
+ }
+ if (fpr_index < 16) {
+ registers[arg_index] = fprs[fpr_index++];
+ } else {
+ registers[arg_index] = stack_args[arg_index];
+ }
+ arg_index++;
+ break;
+ }
+ case 'J': {
+ arg_index += 2;
+ break;
+ }
+ default: {
+ arg_index++;
+ break;
+ }
+ }
+ }
+}
+
+extern "C" void NterpSetupArm32Fprs(const char* shorty,
+ uint32_t dex_register,
+ uint32_t stack_index,
+ uint32_t* fprs,
+ uint32_t* registers,
+ uint32_t* stack_args) {
+ // Note `shorty` has already the returned type removed.
+ ScopedAssertNoThreadSuspension sants("In nterp");
+ uint32_t fpr_double_index = 0;
+ uint32_t fpr_index = 0;
+ for (uint32_t shorty_index = 0; shorty[shorty_index] != '\0'; ++shorty_index) {
+ char arg_type = shorty[shorty_index];
+ switch (arg_type) {
+ case 'D': {
+ // Double should not overlap with float.
+ fpr_double_index = std::max(fpr_double_index, RoundUp(fpr_index, 2));
+ if (fpr_double_index < 16) {
+ fprs[fpr_double_index++] = registers[dex_register++];
+ fprs[fpr_double_index++] = registers[dex_register++];
+ stack_index += 2;
+ } else {
+ stack_args[stack_index++] = registers[dex_register++];
+ stack_args[stack_index++] = registers[dex_register++];
+ }
+ break;
+ }
+ case 'F': {
+ if (fpr_index % 2 == 0) {
+ fpr_index = std::max(fpr_double_index, fpr_index);
+ }
+ if (fpr_index < 16) {
+ fprs[fpr_index++] = registers[dex_register++];
+ stack_index++;
+ } else {
+ stack_args[stack_index++] = registers[dex_register++];
+ }
+ break;
+ }
+ case 'J': {
+ stack_index += 2;
+ dex_register += 2;
+ break;
+ }
+ default: {
+ stack_index++;
+ dex_register++;
+ break;
+ }
+ }
+ }
+}
+
+#endif
+
extern "C" const dex::CodeItem* NterpGetCodeItem(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) {
ScopedAssertNoThreadSuspension sants("In nterp");
@@ -294,6 +399,7 @@
} else if (resolved_method->GetDeclaringClass()->IsStringClass()
&& !resolved_method->IsStatic()
&& resolved_method->IsConstructor()) {
+ CHECK_NE(invoke_type, kSuper);
resolved_method = WellKnownClasses::StringInitToStringFactory(resolved_method);
// Or the result with 1 to notify to nterp this is a string init method. We
// also don't cache the result as we don't want nterp to have its fast path always