Fixing structure of native frame for Generic JNI
This changes the layout of the callee-save frame used in generic
JNI to be consistent with the JNI compiler, that is, the SIRT is
inline (above the method reference). Now the location of the
"this" object is consistent.
Change-Id: Ibad0882680712cb640b4c70ada0229ef7cf4e62c
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index def7b68..d28b0fe 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -219,8 +219,15 @@
} else {
const void* method_code = GetQuickGenericJniTrampoline();
mirror::ArtMethod* callee_save_method = runtime_->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
+
+ // Compute Sirt size, as Sirt goes into frame
+ MethodHelper mh(method);
+ uint32_t sirt_refs = mh.GetNumberOfReferenceArgsWithoutReceiver() + 1;
+ uint32_t sirt_size = StackIndirectReferenceTable::SizeOf(sirt_refs);
+
OatFile::OatMethod oat_method = CreateOatMethod(method_code,
- callee_save_method->GetFrameSizeInBytes(),
+ callee_save_method->GetFrameSizeInBytes() +
+ sirt_size,
callee_save_method->GetCoreSpillMask(),
callee_save_method->GetFpSpillMask(),
nullptr,
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index ffd7b41..c5219a6 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -364,7 +364,7 @@
OatClass* oat_class = oat_classes_[oat_class_index];
CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
- if (compiled_method != NULL) {
+ if (compiled_method != nullptr) {
const std::vector<uint8_t>* portable_code = compiled_method->GetPortableCode();
const std::vector<uint8_t>* quick_code = compiled_method->GetQuickCode();
if (portable_code != nullptr) {
@@ -495,6 +495,33 @@
if (compiler_driver_->IsImage()) {
+ // Derive frame size and spill masks for native methods without code:
+ // These are generic JNI methods...
+ if (is_native && compiled_method == nullptr) {
+ // Compute Sirt size as putting _every_ reference into it, even null ones.
+ uint32_t s_len;
+ const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx), &s_len);
+ DCHECK(shorty != nullptr);
+ uint32_t refs = 1; // Native method always has "this" or class.
+ for (uint32_t i = 1; i < s_len; ++i) {
+ if (shorty[i] == 'L') {
+ refs++;
+ }
+ }
+ size_t sirt_size = StackIndirectReferenceTable::GetAlignedSirtSize(refs);
+
+ // Get the generic spill masks and base frame size.
+ mirror::ArtMethod* callee_save_method =
+ Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
+
+ frame_size_in_bytes = callee_save_method->GetFrameSizeInBytes() + sirt_size;
+ core_spill_mask = callee_save_method->GetCoreSpillMask();
+ fp_spill_mask = callee_save_method->GetFpSpillMask();
+ mapping_table_offset = 0;
+ vmap_table_offset = 0;
+ gc_map_offset = 0;
+ }
+
ClassLinker* linker = Runtime::Current()->GetClassLinker();
// Unchecked as we hold mutator_lock_ on entry.
ScopedObjectAccessUnchecked soa(Thread::Current());