diff options
author | Jeff Hao <jeffhao@google.com> | 2013-05-08 10:59:04 -0700 |
---|---|---|
committer | Jeff Hao <jeffhao@google.com> | 2013-05-10 17:16:00 -0700 |
commit | 167436311a08a65dea28dda079a137893821c9c7 (patch) | |
tree | 4754f47306a0ffa0ad97635015d9596b427dd425 /src | |
parent | c44f68fb6a6d55c0df28dd05b93d8906ec20bd08 (diff) | |
download | android_art-167436311a08a65dea28dda079a137893821c9c7.tar.gz android_art-167436311a08a65dea28dda079a137893821c9c7.tar.bz2 android_art-167436311a08a65dea28dda079a137893821c9c7.zip |
Improve interpreter to interpreter invokes.
The interpreter constructs a shadow frame instead of arg array to make
interpreter to interpreter transitions faster. This adds a pointer to
an entry for the interpreter to each method.
Change-Id: If48911d3aa3470847b8548a9e92090b829f4f254
Diffstat (limited to 'src')
-rw-r--r-- | src/class_linker.cc | 16 | ||||
-rw-r--r-- | src/class_linker_test.cc | 25 | ||||
-rw-r--r-- | src/compiler/driver/compiler_driver.cc | 3 | ||||
-rw-r--r-- | src/interpreter/interpreter.cc | 138 | ||||
-rw-r--r-- | src/interpreter/interpreter.h | 3 | ||||
-rw-r--r-- | src/invoke_arg_array_builder.h | 58 | ||||
-rw-r--r-- | src/mirror/abstract_method.cc | 2 | ||||
-rw-r--r-- | src/mirror/abstract_method.h | 24 | ||||
-rw-r--r-- | src/oat/runtime/support_interpreter.cc | 16 | ||||
-rw-r--r-- | src/stack.h | 5 |
10 files changed, 188 insertions, 102 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index e55fe78790..759bc0c755 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -74,6 +74,8 @@ namespace art { +extern "C" JValue artInterpreterToQuickEntry(Thread* self, ShadowFrame* shadow_frame); + static void ThrowNoClassDefFoundError(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2))) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -1037,6 +1039,12 @@ void ClassLinker::InitFromImageCallback(mirror::Object* obj, void* arg) { // Check if object is a method without its code set and point it to the resolution trampoline. if (obj->IsMethod()) { mirror::AbstractMethod* method = obj->AsMethod(); + // Install entry point from interpreter. + if (method->GetCode() == NULL && !method->IsNative() && !method->IsProxyMethod()) { + method->SetEntryPointFromInterpreter(interpreter::EnterInterpreterFromInterpreter); + } else { + method->SetEntryPointFromInterpreter(artInterpreterToQuickEntry); + } if (method->GetCode() == NULL) { method->SetCode(GetResolutionTrampoline()); } @@ -1598,6 +1606,13 @@ static void LinkCode(SirtRef<mirror::AbstractMethod>& method, const OatFile::Oat const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index); oat_method.LinkMethod(method.get()); + // Install entry point from interpreter. + if (method->GetCode() == NULL && !method->IsNative() && !method->IsProxyMethod()) { + method->SetEntryPointFromInterpreter(interpreter::EnterInterpreterFromInterpreter); + } else { + method->SetEntryPointFromInterpreter(artInterpreterToQuickEntry); + } + Runtime* runtime = Runtime::Current(); if (method->IsAbstract()) { method->SetCode(GetAbstractMethodErrorStub()); @@ -2551,6 +2566,7 @@ mirror::AbstractMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<mir #else method->SetCode(reinterpret_cast<void*>(art_portable_proxy_invoke_handler)); #endif + method->SetEntryPointFromInterpreter(artInterpreterToQuickEntry); return method; } diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc index c47ce4af8f..94ea9d7db9 100644 --- a/src/class_linker_test.cc +++ b/src/class_linker_test.cc @@ -471,18 +471,19 @@ struct AbstractMethodOffsets : public CheckOffsets<AbstractMethod> { offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, dex_cache_strings_), "dexCacheStrings")); // alphabetical 32-bit - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, access_flags_), "accessFlags")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, code_), "code")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, code_item_offset_), "codeItemOffset")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, core_spill_mask_), "coreSpillMask")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, fp_spill_mask_), "fpSpillMask")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, frame_size_in_bytes_), "frameSizeInBytes")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, native_gc_map_), "gcMap")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, mapping_table_), "mappingTable")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, method_dex_index_), "methodDexIndex")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, method_index_), "methodIndex")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, native_method_), "nativeMethod")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, vmap_table_), "vmapTable")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, access_flags_), "accessFlags")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, code_), "code")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, code_item_offset_), "codeItemOffset")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, core_spill_mask_), "coreSpillMask")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, entry_point_from_interpreter_), "entryPointFromInterpreter")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, fp_spill_mask_), "fpSpillMask")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, frame_size_in_bytes_), "frameSizeInBytes")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, gc_map_), "gcMap")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, mapping_table_), "mappingTable")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, method_dex_index_), "methodDexIndex")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, method_index_), "methodIndex")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, native_method_), "nativeMethod")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(AbstractMethod, vmap_table_), "vmapTable")); }; }; diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc index 5ddd0a69bd..6b7d9e6390 100644 --- a/src/compiler/driver/compiler_driver.cc +++ b/src/compiler/driver/compiler_driver.cc @@ -492,7 +492,7 @@ void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const De bool CompilerDriver::IsImageClass(const std::string& descriptor) const { if (image_classes_ == NULL) { - return true; + return false; } return image_classes_->find(descriptor) != image_classes_->end(); } @@ -1649,7 +1649,6 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t } else if (code_item->insns_size_in_code_units_ < Runtime::Current()->GetSmallModeMethodDexSizeLimit()) { // Do compile small methods. dont_compile = false; - LOG(INFO) << "Compiling a small method: " << PrettyMethod(method_idx, dex_file); } if (!dont_compile) { diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc index b82c632236..9f48e78e17 100644 --- a/src/interpreter/interpreter.cc +++ b/src/interpreter/interpreter.cc @@ -42,6 +42,7 @@ using namespace art::mirror; namespace art { + namespace interpreter { static const int32_t kMaxInt = std::numeric_limits<int32_t>::max(); @@ -50,13 +51,13 @@ static const int64_t kMaxLong = std::numeric_limits<int64_t>::max(); static const int64_t kMinLong = std::numeric_limits<int64_t>::min(); static void UnstartedRuntimeInvoke(Thread* self, AbstractMethod* target_method, - Object* receiver, uint32_t* args, JValue* result) + ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // In a runtime that's not started we intercept certain methods to avoid complicated dependency // problems in core libraries. std::string name(PrettyMethod(target_method)); if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)") { - std::string descriptor(DotToDescriptor(reinterpret_cast<Object*>(args[0])->AsString()->ToModifiedUtf8().c_str())); + std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str())); ClassLoader* class_loader = NULL; // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader(); Class* found = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str(), class_loader); @@ -64,7 +65,7 @@ static void UnstartedRuntimeInvoke(Thread* self, AbstractMethod* target_method, << PrettyDescriptor(descriptor); result->SetL(found); } else if (name == "java.lang.Object java.lang.Class.newInstance()") { - Class* klass = receiver->AsClass(); + Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass(); AbstractMethod* c = klass->FindDeclaredDirectMethod("<init>", "()V"); CHECK(c != NULL); Object* obj = klass->AllocObject(self); @@ -74,8 +75,8 @@ static void UnstartedRuntimeInvoke(Thread* self, AbstractMethod* target_method, } else if (name == "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") { // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail // going the reflective Dex way. - Class* klass = receiver->AsClass(); - String* name = reinterpret_cast<Object*>(args[0])->AsString(); + Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass(); + String* name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString(); Field* found = NULL; FieldHelper fh; ObjectArray<Field>* fields = klass->GetIFields(); @@ -104,25 +105,25 @@ static void UnstartedRuntimeInvoke(Thread* self, AbstractMethod* target_method, result->SetL(found); } else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)") { // Special case array copying without initializing System. - Class* ctype = reinterpret_cast<Object*>(args[0])->GetClass()->GetComponentType(); - jint srcPos = args[1]; - jint dstPos = args[3]; - jint length = args[4]; + Class* ctype = shadow_frame->GetVRegReference(arg_offset)->GetClass()->GetComponentType(); + jint srcPos = shadow_frame->GetVReg(arg_offset + 1); + jint dstPos = shadow_frame->GetVReg(arg_offset + 3); + jint length = shadow_frame->GetVReg(arg_offset + 4); if (!ctype->IsPrimitive()) { - ObjectArray<Object>* src = reinterpret_cast<Object*>(args[0])->AsObjectArray<Object>(); - ObjectArray<Object>* dst = reinterpret_cast<Object*>(args[2])->AsObjectArray<Object>(); + ObjectArray<Object>* src = shadow_frame->GetVRegReference(arg_offset)->AsObjectArray<Object>(); + ObjectArray<Object>* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<Object>(); for (jint i = 0; i < length; ++i) { dst->Set(dstPos + i, src->Get(srcPos + i)); } } else if (ctype->IsPrimitiveChar()) { - CharArray* src = reinterpret_cast<Object*>(args[0])->AsCharArray(); - CharArray* dst = reinterpret_cast<Object*>(args[2])->AsCharArray(); + CharArray* src = shadow_frame->GetVRegReference(arg_offset)->AsCharArray(); + CharArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray(); for (jint i = 0; i < length; ++i) { dst->Set(dstPos + i, src->Get(srcPos + i)); } } else if (ctype->IsPrimitiveInt()) { - IntArray* src = reinterpret_cast<Object*>(args[0])->AsIntArray(); - IntArray* dst = reinterpret_cast<Object*>(args[2])->AsIntArray(); + IntArray* src = shadow_frame->GetVRegReference(arg_offset)->AsIntArray(); + IntArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsIntArray(); for (jint i = 0; i < length; ++i) { dst->Set(dstPos + i, src->Get(srcPos + i)); } @@ -131,7 +132,7 @@ static void UnstartedRuntimeInvoke(Thread* self, AbstractMethod* target_method, } } else { // Not special, continue with regular interpreter execution. - EnterInterpreterFromInvoke(self, target_method, receiver, args, result); + result->SetJ(EnterInterpreterFromInterpreter(self, shadow_frame).GetJ()); } } @@ -402,21 +403,65 @@ static void DoInvoke(Thread* self, MethodHelper& mh, ShadowFrame& shadow_frame, return; } mh.ChangeMethod(target_method); - ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); - if (is_range) { - arg_array.BuildArgArray(shadow_frame, receiver, dec_insn.vC + (type != kStatic ? 1 : 0)); + + const DexFile::CodeItem* code_item = mh.GetCodeItem(); + uint16_t num_regs; + uint16_t num_ins; + if (code_item != NULL) { + num_regs = code_item->registers_size_; + num_ins = code_item->ins_size_; + } else if (target_method->IsAbstract()) { + ThrowLocation throw_location = self->GetCurrentLocationForThrow(); + self->ThrowNewExceptionF(throw_location, "Ljava/lang/AbstractMethodError;", + "abstract method \"%s\"", PrettyMethod(target_method).c_str()); + return; } else { - arg_array.BuildArgArray(shadow_frame, receiver, dec_insn.arg + (type != kStatic ? 1 : 0)); + DCHECK(target_method->IsNative() || target_method->IsProxyMethod()); + num_regs = num_ins = AbstractMethod::NumArgRegisters(mh.GetShorty()); + if (!target_method->IsStatic()) { + num_regs++; + num_ins++; + } } - if (LIKELY(Runtime::Current()->IsStarted())) { - target_method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, - mh.GetShorty()[0]); - } else { - uint32_t* args = arg_array.GetArray(); - if (type != kStatic) { - args++; + + Runtime* runtime = Runtime::Current(); + UniquePtr<ShadowFrame> new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, + target_method, 0)); + size_t cur_reg = num_regs - num_ins; + if (receiver != NULL) { + new_shadow_frame->SetVRegReference(cur_reg, receiver); + ++cur_reg; + } + + size_t arg_offset = (receiver == NULL) ? 0 : 1; + const char* shorty = mh.GetShorty(); + for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, cur_reg++, arg_offset++) { + DCHECK_LT(shorty_pos + 1, mh.GetShortyLength()); + size_t arg_pos = is_range ? dec_insn.vC + arg_offset : dec_insn.arg[arg_offset]; + switch (shorty[shorty_pos + 1]) { + case 'L': { + Object* o = shadow_frame.GetVRegReference(arg_pos); + new_shadow_frame->SetVRegReference(cur_reg, o); + break; + } + case 'J': case 'D': { + uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(arg_pos + 1)) << 32) | + static_cast<uint32_t>(shadow_frame.GetVReg(arg_pos)); + new_shadow_frame->SetVRegLong(cur_reg, wide_value); + cur_reg++; + arg_offset++; + break; + } + default: + new_shadow_frame->SetVReg(cur_reg, shadow_frame.GetVReg(arg_pos)); + break; } - UnstartedRuntimeInvoke(self, target_method, receiver, args, result); + } + + if (LIKELY(runtime->IsStarted())) { + result->SetJ((target_method->GetEntryPointFromInterpreter())(self, new_shadow_frame.get()).GetJ()); + } else { + UnstartedRuntimeInvoke(self, target_method, new_shadow_frame.get(), result, num_regs - num_ins); } mh.ChangeMethod(shadow_frame.GetMethod()); } @@ -1925,5 +1970,42 @@ JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::C return Execute(self, mh, code_item, shadow_frame, JValue()); } +JValue EnterInterpreterFromInterpreter(Thread* self, ShadowFrame* shadow_frame) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (__builtin_frame_address(0) < self->GetStackEnd()) { + ThrowStackOverflowError(self); + return JValue(); + } + + AbstractMethod* method = shadow_frame->GetMethod(); + if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) { + if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(), + true, true)) { + DCHECK(Thread::Current()->IsExceptionPending()); + return JValue(); + } + CHECK(method->GetDeclaringClass()->IsInitializing()); + } + + self->PushShadowFrame(shadow_frame); + + MethodHelper mh(method); + const DexFile::CodeItem* code_item = mh.GetCodeItem(); + JValue result; + if (LIKELY(!method->IsNative())) { + result = Execute(self, mh, code_item, *shadow_frame, JValue()); + } else { + // We don't expect to be asked to interpret native code (which is entered via a JNI compiler + // generated stub) except during testing and image writing. + CHECK(!Runtime::Current()->IsStarted()); + Object* receiver = method->IsStatic() ? NULL : shadow_frame->GetVRegReference(0); + uint32_t* args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1); + UnstartedRuntimeJni(self, method, receiver, args, &result); + } + + self->PopShadowFrame(); + return result; +} + } // namespace interpreter } // namespace art diff --git a/src/interpreter/interpreter.h b/src/interpreter/interpreter.h index cf47b682ae..94fdff1d33 100644 --- a/src/interpreter/interpreter.h +++ b/src/interpreter/interpreter.h @@ -47,6 +47,9 @@ extern JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, ShadowFrame& shadow_frame) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); +extern JValue EnterInterpreterFromInterpreter(Thread* self, ShadowFrame* shadow_frame) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + } // namespace interpreter } // namespace art diff --git a/src/invoke_arg_array_builder.h b/src/invoke_arg_array_builder.h index a6e99a52d9..b57d60a70f 100644 --- a/src/invoke_arg_array_builder.h +++ b/src/invoke_arg_array_builder.h @@ -162,60 +162,10 @@ class ArgArray { } } - void BuildArgArray(const ShadowFrame& shadow_frame, mirror::Object* receiver, uint32_t range_start) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // Set receiver if non-null (method is not static) - if (receiver != NULL) { - Append(reinterpret_cast<int32_t>(receiver)); - } - for (size_t i = 1, reg_offset = 0; i < shorty_len_; ++i, ++reg_offset) { - switch (shorty_[i]) { - case 'Z': - case 'B': - case 'C': - case 'S': - case 'I': - case 'F': - Append(shadow_frame.GetVReg(range_start + reg_offset)); - break; - case 'L': - Append(reinterpret_cast<int32_t>(shadow_frame.GetVRegReference(range_start + reg_offset))); - break; - case 'D': - case 'J': - AppendWide(shadow_frame.GetVRegLong(range_start + reg_offset)); - reg_offset++; - break; - } - } - } - - void BuildArgArray(const ShadowFrame& shadow_frame, mirror::Object* receiver, const uint32_t* arg_regs) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - // Set receiver if non-null (method is not static) - if (receiver != NULL) { - Append(reinterpret_cast<int32_t>(receiver)); - } - for (size_t i = 1, reg_offset = 0; i < shorty_len_; ++i, ++reg_offset) { - switch (shorty_[i]) { - case 'Z': - case 'B': - case 'C': - case 'S': - case 'I': - case 'F': - Append(shadow_frame.GetVReg(arg_regs[reg_offset])); - break; - case 'L': - Append(reinterpret_cast<int32_t>(shadow_frame.GetVRegReference(arg_regs[reg_offset]))); - break; - case 'D': - case 'J': - AppendWide(shadow_frame.GetVRegLong(arg_regs[reg_offset])); - reg_offset++; - break; - } - } + void BuildArgArray(ShadowFrame* shadow_frame, uint32_t arg_offset) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + arg_array_ = shadow_frame->GetVRegArgs(arg_offset); + num_bytes_ = (shadow_frame->NumberOfVRegs() - arg_offset) * 4; } private: diff --git a/src/mirror/abstract_method.cc b/src/mirror/abstract_method.cc index 559b5581ac..c351ce841d 100644 --- a/src/mirror/abstract_method.cc +++ b/src/mirror/abstract_method.cc @@ -344,7 +344,7 @@ void AbstractMethod::RegisterNative(Thread* self, const void* native_method) { #else UNIMPLEMENTED(FATAL); #endif - SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), + SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, gc_map_), reinterpret_cast<const uint8_t*>(native_method), false); } } diff --git a/src/mirror/abstract_method.h b/src/mirror/abstract_method.h index 9440915731..e95537693b 100644 --- a/src/mirror/abstract_method.h +++ b/src/mirror/abstract_method.h @@ -31,11 +31,14 @@ union JValue; struct MethodClassOffsets; struct MethodOffsets; class StringPiece; +class ShadowFrame; namespace mirror { class StaticStorageBase; +typedef JValue (EntryPointFromInterpreter)(Thread* self, ShadowFrame* shadow_frame); + // C++ mirror of java.lang.reflect.Method and java.lang.reflect.Constructor class MANAGED AbstractMethod : public Object { public: @@ -189,6 +192,14 @@ class MANAGED AbstractMethod : public Object { void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, char result_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + EntryPointFromInterpreter* GetEntryPointFromInterpreter() const { + return GetFieldPtr<EntryPointFromInterpreter*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, entry_point_from_interpreter_), false); + } + + void SetEntryPointFromInterpreter(EntryPointFromInterpreter* entry_point_from_interpreter) { + SetFieldPtr<EntryPointFromInterpreter*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, entry_point_from_interpreter_), entry_point_from_interpreter, false); + } + const void* GetCode() const { return GetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_), false); } @@ -293,11 +304,10 @@ class MANAGED AbstractMethod : public Object { void SetOatVmapTableOffset(uint32_t vmap_table_offset); const uint8_t* GetNativeGcMap() const { - return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), false); + return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, gc_map_), false); } void SetNativeGcMap(const uint8_t* data) { - SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), data, - false); + SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, gc_map_), data, false); } // When building the oat need a convenient place to stuff the offset of the native GC map. @@ -424,6 +434,7 @@ class MANAGED AbstractMethod : public Object { // Compiled code associated with this method for callers from managed code. // May be compiled managed code or a bridge for invoking a native method. + // TODO: Break apart this into portable and quick. const void* code_; // Offset to the CodeItem. @@ -432,14 +443,17 @@ class MANAGED AbstractMethod : public Object { // Architecture-dependent register spill mask uint32_t core_spill_mask_; + // Called by the interpreter to execute this method. + EntryPointFromInterpreter* entry_point_from_interpreter_; + // Architecture-dependent register spill mask uint32_t fp_spill_mask_; // Total size in bytes of the frame size_t frame_size_in_bytes_; - // Garbage collection map of native PC offsets to reference bitmaps. - const uint8_t* native_gc_map_; + // Garbage collection map of native PC offsets (quick) or dex PCs (portable) to reference bitmaps. + const uint8_t* gc_map_; // Mapping from native pc to dex pc const uint32_t* mapping_table_; diff --git a/src/oat/runtime/support_interpreter.cc b/src/oat/runtime/support_interpreter.cc index 3ab234fecf..6a65cea3a8 100644 --- a/src/oat/runtime/support_interpreter.cc +++ b/src/oat/runtime/support_interpreter.cc @@ -18,6 +18,7 @@ #include "callee_save_frame.h" #include "dex_file-inl.h" #include "interpreter/interpreter.h" +#include "invoke_arg_array_builder.h" #include "mirror/abstract_method-inl.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" @@ -108,4 +109,19 @@ extern "C" uint64_t artInterpreterEntry(mirror::AbstractMethod* method, Thread* return result.GetJ(); } +extern "C" JValue artInterpreterToQuickEntry(Thread* self, ShadowFrame* shadow_frame) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::AbstractMethod* method = shadow_frame->GetMethod(); + MethodHelper mh(method); + const DexFile::CodeItem* code_item = mh.GetCodeItem(); + + uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_; + ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); + arg_array.BuildArgArray(shadow_frame, arg_offset); + JValue result; + method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), &result, mh.GetShorty()[0]); + + return result; +} + } // namespace art diff --git a/src/stack.h b/src/stack.h index e2148a34d8..8e597b2b3a 100644 --- a/src/stack.h +++ b/src/stack.h @@ -145,6 +145,11 @@ class ShadowFrame { } } + // Get view of vregs as range of consecutive arguments starting at i. + uint32_t* GetVRegArgs(size_t i) { + return &vregs_[i]; + } + void SetVReg(size_t i, int32_t val) { DCHECK_LT(i, NumberOfVRegs()); uint32_t* vreg = &vregs_[i]; |