Switch interpreter: Split the method in ASAN to avoid huge frames
Bug: 117341496
Test: "./art/test.py -b -r --interpreter --host --64" in ASAN
Change-Id: I6945bf78789588058b1668bf16da9ee1b3ff26b5
diff --git a/runtime/interpreter/interpreter_switch_impl-inl.h b/runtime/interpreter/interpreter_switch_impl-inl.h
index be4b807..8afaed5 100644
--- a/runtime/interpreter/interpreter_switch_impl-inl.h
+++ b/runtime/interpreter/interpreter_switch_impl-inl.h
@@ -1901,11 +1901,34 @@
bool& exit_interpreter_loop;
};
-// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
-// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
-// fixed.
+// Don't inline in ASAN. It would create massive stack frame.
+#ifdef ADDRESS_SANITIZER
+#define ASAN_NO_INLINE NO_INLINE
+#else
+#define ASAN_NO_INLINE ALWAYS_INLINE
+#endif
+
+#define OPCODE_CASE(OPCODE, OPCODE_NAME, NAME, FORMAT, i, a, e, v) \
+template<bool do_access_check, bool transaction_active> \
+ASAN_NO_INLINE static bool OP_##OPCODE_NAME( \
+ SwitchImplContext* ctx, \
+ const instrumentation::Instrumentation* instrumentation, \
+ Thread* self, \
+ ShadowFrame& shadow_frame, \
+ uint16_t dex_pc, \
+ const Instruction* inst, \
+ uint16_t inst_data, \
+ const Instruction*& next, \
+ bool& exit) REQUIRES_SHARED(Locks::mutator_lock_) { \
+ InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \
+ ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit); \
+ return LIKELY(handler.OPCODE_NAME()); \
+}
+DEX_INSTRUCTION_LIST(OPCODE_CASE)
+#undef OPCODE_CASE
+
template<bool do_access_check, bool transaction_active>
-ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
+void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
Thread* self = ctx->self;
const CodeItemDataAccessor& accessor = ctx->accessor;
ShadowFrame& shadow_frame = ctx->shadow_frame;
@@ -1935,9 +1958,9 @@
case OPCODE: { \
DCHECK_EQ(self->IsExceptionPending(), (OPCODE == Instruction::MOVE_EXCEPTION)); \
next = inst->RelativeAt(Instruction::SizeInCodeUnits(Instruction::FORMAT)); \
- InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \
+ bool success = OP_##OPCODE_NAME<do_access_check, transaction_active>( \
ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit); \
- if (handler.OPCODE_NAME() && LIKELY(!interpret_one_instruction)) { \
+ if (success && LIKELY(!interpret_one_instruction)) { \
DCHECK(!exit) << NAME; \
continue; \
} \