Merge "Renamed ReferenceMapVisitor to prevent confusion with art version." into ics-mr1-plus-art
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 110b393..6f7fdfb 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -165,6 +165,8 @@
; Temporary runtime support, will be removed in the future
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+declare void @art_mark_gc_card_from_code(%JavaObject*, %JavaObject*)
+
declare %JavaObject* @art_ensure_resolved_from_code(%JavaObject*,
%JavaObject*,
i32,
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index db1a3de..1b9bcf5 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -933,6 +933,17 @@
AttrListPtr func_F2I_PAL;
func_F2I->setAttributes(func_F2I_PAL);
+Function* func_art_mark_gc_card_from_code = mod->getFunction("art_mark_gc_card_from_code");
+if (!func_art_mark_gc_card_from_code) {
+func_art_mark_gc_card_from_code = Function::Create(
+ /*Type=*/FuncTy_28,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_mark_gc_card_from_code", mod); // (external, no body)
+func_art_mark_gc_card_from_code->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_art_mark_gc_card_from_code_PAL;
+func_art_mark_gc_card_from_code->setAttributes(func_art_mark_gc_card_from_code_PAL);
+
Function* func_art_ensure_resolved_from_code = mod->getFunction("art_ensure_resolved_from_code");
if (!func_art_ensure_resolved_from_code) {
func_art_ensure_resolved_from_code = Function::Create(
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 153d99a..fa8a827 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2252,6 +2252,12 @@
}
}
+void MethodCompiler::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
+ // Using runtime support, let the target can override by InlineAssembly.
+ llvm::Function* runtime_func = irb_.GetRuntime(MarkGCCard);
+
+ irb_.CreateCall2(runtime_func, value, target_addr);
+}
void
MethodCompiler::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
@@ -2354,12 +2360,14 @@
llvm::Value* new_value = EmitLoadDalvikReg(dec_insn.vA, elem_jty, kArray);
- if (elem_jty == kObject) { // If put an object, check the type.
+ if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
llvm::Function* runtime_func = irb_.GetRuntime(CheckPutArrayElement);
irb_.CreateCall2(runtime_func, new_value, array_addr);
EmitGuard_ExceptionLandingPad(dex_pc);
+
+ EmitMarkGCCard(new_value, array_addr);
}
irb_.CreateStore(new_value, array_elem_addr);
@@ -2488,6 +2496,10 @@
// TODO: Check is_volatile. We need to generate atomic store instruction
// when is_volatile is true.
irb_.CreateStore(new_value, field_addr);
+
+ if (field_jty == kObject) { // If put an object, mark the GC card table.
+ EmitMarkGCCard(new_value, object_addr);
+ }
}
irb_.CreateBr(GetNextBasicBlock(dex_pc));
@@ -2704,6 +2716,10 @@
// TODO: Check is_volatile. We need to generate atomic store instruction
// when is_volatile is true.
irb_.CreateStore(new_value, static_field_addr);
+
+ if (field_jty == kObject) { // If put an object, mark the GC card table.
+ EmitMarkGCCard(new_value, static_storage_addr);
+ }
}
irb_.CreateBr(GetNextBasicBlock(dex_pc));
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 0bfdf5d..7a5d66f 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -260,6 +260,8 @@
#undef GEN_INSN_ARGS
+ // GC card table helper function
+ void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
// Shadow frame helper function
void EmitPopShadowFrame();
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index 4183df6..a8a3ed7 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -16,6 +16,7 @@
#include "runtime_support_builder.h"
+#include "card_table.h"
#include "ir_builder.h"
#include "shadow_frame.h"
#include "thread.h"
@@ -38,6 +39,7 @@
IRBuilder& irb)
: context_(context), module_(module), irb_(irb)
{
+ memset(target_runtime_support_func_, 0, sizeof(target_runtime_support_func_));
#define GET_RUNTIME_SUPPORT_FUNC_DECL(ID, NAME) \
do { \
llvm::Function* fn = module_.getFunction(#NAME); \
@@ -162,6 +164,38 @@
OverrideRuntimeSupportFunction(TestSuspend, func);
}
+
+ if (!target_runtime_support_func_[MarkGCCard]) {
+ Function* func = GetRuntimeSupportFunction(MarkGCCard);
+ MakeFunctionInline(func);
+ BasicBlock* basic_block = BasicBlock::Create(context_, "entry", func);
+ irb_.SetInsertPoint(basic_block);
+ Function::arg_iterator arg_iter = func->arg_begin();
+ Value* value = arg_iter++;
+ Value* target_addr = arg_iter++;
+
+ llvm::Value* is_value_null = irb_.CreateICmpEQ(value, irb_.getJNull());
+
+ llvm::BasicBlock* block_value_is_null = BasicBlock::Create(context_, "value_is_null", func);
+ llvm::BasicBlock* block_mark_gc_card = BasicBlock::Create(context_, "mark_gc_card", func);
+
+ irb_.CreateCondBr(is_value_null, block_value_is_null, block_mark_gc_card);
+
+ irb_.SetInsertPoint(block_value_is_null);
+ irb_.CreateRetVoid();
+
+ irb_.SetInsertPoint(block_mark_gc_card);
+ Function* get_thread = GetRuntimeSupportFunction(GetCurrentThread);
+ Value* thread = irb_.CreateCall(get_thread);
+ Value* card_table = irb_.LoadFromObjectOffset(thread,
+ Thread::CardTableOffset().Int32Value(),
+ irb_.getInt8Ty()->getPointerTo());
+ Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
+ Value* card_no = irb_.CreateLShr(target_addr_int, irb_.getPtrEquivInt(GC_CARD_SHIFT));
+ Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
+ irb_.CreateStore(irb_.getInt8(GC_CARD_DIRTY), card_table_entry);
+ irb_.CreateRetVoid();
+ }
}
} // namespace compiler_llvm
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index 498502a..2f3a6fa 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -61,6 +61,7 @@
V(InitializeStaticStorage, art_initialize_static_storage_from_code) \
V(IsExceptionPending, art_is_exception_pending_from_code) \
V(FindCatchBlock, art_find_catch_block_from_code) \
+ V(MarkGCCard, art_mark_gc_card_from_code) \
V(EnsureResolved, art_ensure_resolved_from_code) \
V(FixStub, art_fix_stub_from_code) \
V(ProxyInvokeHandler, art_proxy_invoke_handler_from_code) \
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index c526847..0fd3611 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -39,6 +39,9 @@
// Thread
//----------------------------------------------------------------------------
+// This is used by other runtime support functions, NOT FROM CODE. The REAL GetCurrentThread is
+// implemented by IRBuilder. (So, ARM can't return R9 in this function.)
+// TODO: Maybe remove these which are implemented by IRBuilder after refactor runtime support.
Thread* art_get_current_thread_from_code() {
#if defined(__i386__)
Thread* ptr;
@@ -53,6 +56,7 @@
}
void art_set_current_thread_from_code(void* thread_object_addr) {
+ LOG(FATAL) << "Implemented by IRBuilder.";
}
void art_lock_object_from_code(Object* obj) {
@@ -77,23 +81,24 @@
}
void art_push_shadow_frame_from_code(void* new_shadow_frame) {
- Thread* thread = art_get_current_thread_from_code();
- thread->PushShadowFrame(static_cast<ShadowFrame*>(new_shadow_frame));
+ LOG(FATAL) << "Implemented by IRBuilder.";
}
void art_pop_shadow_frame_from_code() {
- Thread* thread = art_get_current_thread_from_code();
- thread->PopShadowFrame();
+ LOG(FATAL) << "Implemented by IRBuilder.";
}
-
+void art_mark_gc_card_from_code(void *, void*) {
+ LOG(FATAL) << "Implemented by IRBuilder.";
+}
//----------------------------------------------------------------------------
// Exception
//----------------------------------------------------------------------------
bool art_is_exception_pending_from_code() {
- return art_get_current_thread_from_code()->IsExceptionPending();
+ LOG(FATAL) << "Implemented by IRBuilder.";
+ return false;
}
void art_throw_div_zero_from_code() {
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index 1553dd8..381c7f0 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -139,7 +139,6 @@
void* arg = reinterpret_cast<void*>(this);
const std::vector<Space*>& spaces = heap_->GetSpaces();
for (size_t i = 0; i < spaces.size(); ++i) {
-#if !defined(ART_USE_LLVM_COMPILER)
#ifndef NDEBUG
uintptr_t begin = reinterpret_cast<uintptr_t>(spaces[i]->Begin());
uintptr_t end = reinterpret_cast<uintptr_t>(spaces[i]->End());
@@ -155,12 +154,6 @@
mark_bitmap_->ScanWalk(begin, end, &MarkSweep::ScanBitmapCallback, arg);
}
#endif
-#else
- // TODO: Implement card marking.
- uintptr_t begin = reinterpret_cast<uintptr_t>(spaces[i]->Begin());
- uintptr_t end = reinterpret_cast<uintptr_t>(spaces[i]->End());
- mark_bitmap_->ScanWalk(begin, end, &MarkSweep::ScanBitmapCallback, arg);
-#endif
}
finger_ = reinterpret_cast<Object*>(~0);
// TODO: tune the frequency of emptying the mark stack
diff --git a/src/runtime_linux.cc b/src/runtime_linux.cc
index 4214003..c96b1e5 100644
--- a/src/runtime_linux.cc
+++ b/src/runtime_linux.cc
@@ -209,7 +209,7 @@
memset(&action, 0, sizeof(action));
sigemptyset(&action.sa_mask);
action.sa_sigaction = HandleUnexpectedSignal;
- action.sa_flags = SA_RESTART | SA_SIGINFO;
+ action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
int rc = 0;
rc += sigaction(SIGILL, &action, NULL);
diff --git a/src/thread.cc b/src/thread.cc
index ca8922b..3892c23 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -18,6 +18,7 @@
#include <dynamic_annotations.h>
#include <pthread.h>
+#include <signal.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/time.h>
@@ -75,17 +76,21 @@
card_table_ = Runtime::Current()->GetHeap()->GetCardTable()->GetBiasedBegin();
}
+#if !defined(__APPLE__)
static void UnimplementedEntryPoint() {
UNIMPLEMENTED(FATAL);
}
+#endif
void Thread::InitFunctionPointers() {
+#if !defined(__APPLE__) // The Mac GCC is too old to accept this code.
// Insert a placeholder so we can easily tell if we call an unimplemented entry point.
uintptr_t* begin = reinterpret_cast<uintptr_t*>(&entrypoints_);
uintptr_t* end = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(begin) + sizeof(entrypoints_));
for (uintptr_t* it = begin; it != end; ++it) {
*it = reinterpret_cast<uintptr_t>(UnimplementedEntryPoint);
}
+#endif
InitEntryPoints(&entrypoints_);
}
@@ -185,6 +190,43 @@
return stack_size;
}
+static void SigAltStack(stack_t* new_stack, stack_t* old_stack) {
+ if (sigaltstack(new_stack, old_stack) == -1) {
+ PLOG(FATAL) << "sigaltstack failed";
+ }
+}
+
+static void SetUpAlternateSignalStack() {
+ // Create and set an alternate signal stack.
+ stack_t ss;
+ ss.ss_sp = new uint8_t[SIGSTKSZ];
+ ss.ss_size = SIGSTKSZ;
+ ss.ss_flags = 0;
+ CHECK(ss.ss_sp != NULL);
+ SigAltStack(&ss, NULL);
+
+ // Double-check that it worked.
+ ss.ss_sp = NULL;
+ SigAltStack(NULL, &ss);
+ VLOG(threads) << "Alternate signal stack is " << PrettySize(ss.ss_size) << " at " << ss.ss_sp;
+}
+
+static void TearDownAlternateSignalStack() {
+ // Get the pointer so we can free the memory.
+ stack_t ss;
+ SigAltStack(NULL, &ss);
+ uint8_t* allocated_signal_stack = reinterpret_cast<uint8_t*>(ss.ss_sp);
+
+ // Tell the kernel to stop using it.
+ ss.ss_sp = NULL;
+ ss.ss_flags = SS_DISABLE;
+ ss.ss_size = 0;
+ SigAltStack(&ss, NULL);
+
+ // Free it.
+ delete[] allocated_signal_stack;
+}
+
void Thread::Create(Object* peer, size_t stack_size) {
CHECK(peer != NULL);
@@ -219,6 +261,7 @@
// thread hasn't been through here already...
CHECK(Thread::Current() == NULL);
+ SetUpAlternateSignalStack();
InitCpu();
InitFunctionPointers();
InitCardTable();
@@ -878,6 +921,8 @@
delete debug_invoke_req_;
delete trace_stack_;
delete name_;
+
+ TearDownAlternateSignalStack();
}
void Thread::HandleUncaughtExceptions() {