Exception and suspend count polling on JNI bridge return.
Change-Id: I0e5597fcbdcdb88100b18d63323e7ba8d27f13fe
diff --git a/src/assembler.h b/src/assembler.h
index cc02c69..c98a6b7 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -5,7 +5,9 @@
#include "src/logging.h"
#include "src/macros.h"
+#include "src/managed_register.h"
#include "src/memory_region.h"
+#include "src/offsets.h"
namespace art {
@@ -83,6 +85,52 @@
friend class AssemblerBuffer;
};
+// Parent of all queued slow paths, emitted during finalization
+class SlowPath {
+ public:
+ SlowPath() : next_(NULL) {}
+ virtual ~SlowPath() {}
+
+ Label* Continuation() { return &continuation_; }
+ Label* Entry() { return &entry_; }
+ // Generate code for slow path
+ virtual void Emit(Assembler *sp_asm) = 0;
+
+ protected:
+ // Entry branched to by fast path
+ Label entry_;
+ // Optional continuation that is branched to at the end of the slow path
+ Label continuation_;
+ // Next in linked list of slow paths
+ SlowPath *next_;
+
+ friend class AssemblerBuffer;
+ DISALLOW_COPY_AND_ASSIGN(SlowPath);
+};
+
+// Slowpath entered when Thread::Current()->_exception is non-null
+class ExceptionSlowPath : public SlowPath {
+ public:
+ ExceptionSlowPath() {}
+ virtual void Emit(Assembler *sp_asm);
+};
+
+// Slowpath entered when Thread::Current()->_suspend_count is non-zero
+class SuspendCountSlowPath : public SlowPath {
+ public:
+ SuspendCountSlowPath(ManagedRegister return_reg,
+ FrameOffset return_save_location,
+ size_t return_size) :
+ return_register_(return_reg), return_save_location_(return_save_location),
+ return_size_(return_size) {}
+ virtual void Emit(Assembler *sp_asm);
+
+ private:
+ // Remember how to save the return value
+ const ManagedRegister return_register_;
+ const FrameOffset return_save_location_;
+ const size_t return_size_;
+};
class AssemblerBuffer {
public:
@@ -113,6 +161,27 @@
fixup_ = fixup;
}
+ void EnqueueSlowPath(SlowPath* slowpath) {
+ if (slow_path_ == NULL) {
+ slow_path_ = slowpath;
+ } else {
+ SlowPath* cur = slow_path_;
+ for ( ; cur->next_ != NULL ; cur = cur->next_) {}
+ cur->next_ = slowpath;
+ }
+ }
+
+ void EmitSlowPaths(Assembler* sp_asm) {
+ SlowPath* cur = slow_path_;
+ SlowPath* next = NULL;
+ slow_path_ = NULL;
+ for ( ; cur != NULL ; cur = next) {
+ cur->Emit(sp_asm);
+ next = cur->next_;
+ delete cur;
+ }
+ }
+
// Get the size of the emitted code.
size_t Size() const {
CHECK_GE(cursor_, contents_);
@@ -203,6 +272,9 @@
AssemblerFixup* fixup_;
bool fixups_processed_;
+ // Head of linked list of slow paths
+ SlowPath* slow_path_;
+
byte* cursor() const { return cursor_; }
byte* limit() const { return limit_; }
size_t Capacity() const {