Implement Link-loading and pass 62 tests in JniInternalTest.
The passed tests include the 12 originally ARM-only tests. Now it works
on x86 as well if defined(ART_USE_LLVM_COMPILER).
Change-Id: I03092637fa4f0979ca77e0cac06e5d31a867e465
diff --git a/src/common_test.h b/src/common_test.h
index 7083b8c..7087c70 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -24,6 +24,7 @@
#include "class_linker.h"
#include "class_loader.h"
#include "compiler.h"
+#include "compiler_llvm/utils_llvm.h"
#include "constants.h"
#include "dex_file.h"
#include "file.h"
@@ -174,8 +175,10 @@
}
static void MakeExecutable(const std::vector<uint8_t>& code) {
+#if !defined(ART_USE_LLVM_COMPILER) // LLVM compilation uses ELF instead
CHECK_NE(code.size(), 0U);
MakeExecutable(&code[0], code.size());
+#endif
}
// Create an OatMethod based on pointers (for unit tests)
@@ -232,7 +235,11 @@
&compiled_method->GetVmapTable()[0],
NULL,
method_invoke_stub);
+#if !defined(ART_USE_LLVM_COMPILER)
oat_method.LinkMethodPointers(method);
+#else
+ LLVMLinkLoadMethod("-0", method);
+#endif
} else {
MakeExecutable(runtime_->GetAbstractMethodErrorStubArray());
const void* method_code = runtime_->GetAbstractMethodErrorStubArray()->GetData();
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index 45c4bb7..7a2857c 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -143,6 +143,8 @@
target_options.FloatABIType = llvm::FloatABI::Soft;
target_options.UseSoftFloat = false;
+ target_options.NoFramePointerElim = true;
+ target_options.NoFramePointerElimNonLeaf = true;
// Create the llvm::TargetMachine
llvm::TargetMachine* target_machine =
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 56f0b07..0985894 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -55,8 +55,8 @@
CompilerLLVM::CompilerLLVM(Compiler* compiler, InstructionSet insn_set)
-: compiler_(compiler), compiler_lock_("llvm_compiler_lock"),
- insn_set_(insn_set), cunit_counter_(0) {
+ : compiler_(compiler), compiler_lock_("llvm_compiler_lock"),
+ insn_set_(insn_set), cunit_counter_(0) {
// Initialize LLVM libraries
pthread_once(&llvm_initialized, InitializeLLVM);
@@ -69,6 +69,7 @@
void CompilerLLVM::EnsureCompilationUnit() {
+ MutexLock GUARD(compiler_lock_);
DCHECK_NE(llvm_initialized, PTHREAD_ONCE_INIT);
if (cunit_.get() == NULL) {
cunit_.reset(new CompilationUnit(insn_set_));
diff --git a/src/compiler_llvm/utils_llvm.cc b/src/compiler_llvm/utils_llvm.cc
index 1a8e8a2..a924793 100644
--- a/src/compiler_llvm/utils_llvm.cc
+++ b/src/compiler_llvm/utils_llvm.cc
@@ -14,6 +14,12 @@
* limitations under the License.
*/
+#include <android/librsloader.h>
+#include <cutils/log.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/mman.h>
+
#include "utils_llvm.h"
#include "class_loader.h"
@@ -86,4 +92,112 @@
return long_name;
}
+std::string LLVMStubName(const Method* m) {
+ MethodHelper mh(m);
+ std::string stub_name;
+ if (m->IsStatic()) {
+ stub_name += "ArtSUpcall_";
+ } else {
+ stub_name += "ArtUpcall_";
+ }
+ stub_name += mh.GetShorty();
+
+ return stub_name;
+}
+
+// TODO: Remove these when art_llvm.ll runtime support is ready.
+void art_push_shadow_frame_from_code(void* frame) {
+}
+
+void art_pop_shadow_frame_from_code() {
+}
+
+int art_is_exception_pending_from_code() {
+ return 0;
+}
+
+void art_test_suspend_from_code() {
+}
+
+void art_set_current_thread_from_code(void* thread_object_addr) {
+}
+
+// Linker's call back function. Added some for debugging.
+void* find_sym(void* context, char const* name) {
+ struct func_entry_t {
+ char const* name;
+ size_t name_len;
+ void* addr;
+ };
+
+ static struct func_entry_t const tab[] = {
+#define DEF(NAME, ADDR) \
+ { NAME, sizeof(NAME) - 1, (void *)(&(ADDR)) },
+
+ DEF("art_push_shadow_frame_from_code", art_push_shadow_frame_from_code)
+ DEF("art_pop_shadow_frame_from_code", art_pop_shadow_frame_from_code)
+ DEF("art_is_exception_pending_from_code", art_is_exception_pending_from_code)
+ DEF("art_test_suspend_from_code", art_test_suspend_from_code)
+ DEF("art_set_current_thread_from_code", art_set_current_thread_from_code)
+ DEF("printf", printf)
+ DEF("scanf", scanf)
+ DEF("__isoc99_scanf", scanf)
+ DEF("rand", rand)
+ DEF("time", time)
+ DEF("srand", srand)
+#undef DEF
+ };
+
+ static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t);
+
+ // Note: Since our table is small, we are using trivial O(n) searching
+ // function. For bigger table, it will be better to use binary
+ // search or hash function.
+ size_t i;
+ size_t name_len = strlen(name);
+ for (i = 0; i < tab_size; ++i) {
+ if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
+ return tab[i].addr;
+ }
+ }
+
+ CHECK(0) << "Error: Can't find symbol " << name;
+ return 0;
+}
+
+void LLVMLinkLoadMethod(const std::string& file_name, Method* method) {
+ CHECK(method != NULL);
+
+ int fd = open(file_name.c_str(), O_RDONLY);
+ CHECK(fd >= 0) << "Error: ELF not found: " << file_name;
+
+ struct stat sb;
+ CHECK(fstat(fd, &sb) == 0) << "Error: Unable to stat ELF: " << file_name;
+
+ unsigned char const *image = (unsigned char const *)
+ mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ CHECK(image != MAP_FAILED) << "Error: Unable to mmap ELF: " << file_name;
+
+ RSExecRef relocatable = rsloaderCreateExec(image, sb.st_size, find_sym, 0);
+ CHECK(relocatable) << "Error: Unable to load ELF: " << file_name;
+
+ const void *addr = rsloaderGetSymbolAddress(relocatable, LLVMLongName(method).c_str());
+ CHECK(addr) << "Error: ELF (" << file_name << ") has no symbol " << LLVMLongName(method);
+ method->SetCode(reinterpret_cast<const uint32_t*>(addr));
+
+ method->SetFrameSizeInBytes(0);
+ method->SetCoreSpillMask(0);
+ method->SetFpSpillMask(0);
+ method->SetMappingTable(reinterpret_cast<const uint32_t*>(NULL));
+ method->SetVmapTable(reinterpret_cast<const uint16_t*>(NULL));
+ method->SetGcMap(reinterpret_cast<const uint8_t*>(NULL));
+
+ addr = rsloaderGetSymbolAddress(relocatable, LLVMStubName(method).c_str());
+ CHECK(addr) << "Error: ELF (" << file_name << ") has no symbol " << LLVMStubName(method);
+ method->SetInvokeStub(reinterpret_cast<void (*)(const art::Method*, art::Object*, art::Thread*,
+ art::byte*, art::JValue*)>(addr));
+
+ close(fd);
+}
+
} // namespace art
diff --git a/src/compiler_llvm/utils_llvm.h b/src/compiler_llvm/utils_llvm.h
index a1624d7..fb4da34 100644
--- a/src/compiler_llvm/utils_llvm.h
+++ b/src/compiler_llvm/utils_llvm.h
@@ -33,6 +33,10 @@
// Returns the LLVM function name for the overloaded method 'm'.
std::string LLVMLongName(const Method* m);
+// Returns the LLVM stub function name for the overloaded method 'm'.
+std::string LLVMStubName(const Method* m);
+
+void LLVMLinkLoadMethod(const std::string& file_name, Method* method);
} // namespace art
#endif // ART_SRC_UTILS_LLVM_H_
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index d4ed0cc..65283bd 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -698,6 +698,9 @@
return EXIT_FAILURE;
}
+#if defined(ART_USE_LLVM_COMPILER)
+ LOG(INFO) << "oat=" << oat_location << " elf=" << elf_filename;
+#endif
if (!image) {
LOG(INFO) << "Oat file written successfully: " << oat_location;
return EXIT_SUCCESS;
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index ee801be..61bad43 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -677,6 +677,7 @@
} while (false)
+#if !defined(ART_USE_LLVM_COMPILER)
TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
SirtRef<ClassLoader> class_loader(LoadDex("AllFields"));
runtime_->Start();
@@ -734,6 +735,7 @@
env_->SetObjectField(o, i_fid, s2);
ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
}
+#endif
TEST_F(JniInternalTest, NewLocalRef_NULL) {
EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
@@ -889,7 +891,7 @@
env_->DeleteWeakGlobalRef(o2);
}
-#if defined(__arm__)
+#if defined(__arm__) || defined(ART_USE_LLVM_COMPILER)
TEST_F(JniInternalTest, StaticMainMethod) {
SirtRef<ClassLoader> class_loader(LoadDex("Main"));
CompileDirectMethod(class_loader.get(), "Main", "main", "([Ljava/lang/String;)V");
@@ -1030,6 +1032,37 @@
EXPECT_EQ(DBL_MIN, result.d);
}
+static byte* CreateArgArray(Method* method, JValue* args) {
+ const char* shorty = MethodHelper(method).GetShorty();
+ size_t shorty_len = strlen(shorty);
+ UniquePtr<byte[]> arg_array(new byte[shorty_len * 8]);
+ for (size_t i = 1, offset = 0; i < shorty_len; ++i) {
+ switch (shorty[i]) {
+ case 'Z':
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'I':
+ *reinterpret_cast<uint32_t*>(&arg_array[offset]) = args[i - 1].i;
+ break;
+ case 'F':
+ *reinterpret_cast<float*>(&arg_array[offset]) = args[i - 1].f;
+ break;
+ case 'L':
+ *reinterpret_cast<Object**>(&arg_array[offset]) = args[i - 1].l;
+ break;
+ case 'D':
+ *reinterpret_cast<double*>(&arg_array[offset]) = args[i - 1].d;
+ break;
+ case 'J':
+ *reinterpret_cast<uint64_t*>(&arg_array[offset]) = args[i - 1].j;
+ break;
+ }
+ offset += 8;
+ }
+ return arg_array.release();
+}
+
TEST_F(JniInternalTest, StaticSumIntIntMethod) {
SirtRef<ClassLoader> class_loader(LoadDex("StaticLeafMethods"));
CompileDirectMethod(class_loader.get(), "StaticLeafMethods", "sum", "(II)I");
@@ -1042,37 +1075,67 @@
Method::InvokeStub* stub = method->GetInvokeStub();
- int args[2];
JValue result;
-
+ result.i = -1;
+#if !defined(ART_USE_LLVM_COMPILER)
+ int args[2];
args[0] = 0;
args[1] = 0;
- result.i = -1;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ JValue args[2];
+ args[0].i = 0;
+ args[1].i = 0;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(0, result.i);
+ result.i = 0;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = 1;
args[1] = 2;
- result.i = 0;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = 1;
+ args[1].i = 2;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(3, result.i);
+ result.i = 0;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = -2;
args[1] = 5;
- result.i = 0;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = -2;
+ args[1].i = 5;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(3, result.i);
+ result.i = 1234;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = INT_MAX;
args[1] = INT_MIN;
- result.i = 1234;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = INT_MAX;
+ args[1].i = INT_MIN;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(-1, result.i);
+ result.i = INT_MIN;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = INT_MAX;
args[1] = INT_MAX;
- result.i = INT_MIN;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = INT_MAX;
+ args[1].i = INT_MAX;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(-2, result.i);
}
@@ -1088,42 +1151,77 @@
Method::InvokeStub* stub = method->GetInvokeStub();
- int args[3];
JValue result;
-
+ result.i = -1;
+#if !defined(ART_USE_LLVM_COMPILER)
+ int args[3];
args[0] = 0;
args[1] = 0;
args[2] = 0;
- result.i = -1;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ JValue args[3];
+ args[0].i = 0;
+ args[1].i = 0;
+ args[2].i = 0;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(0, result.i);
+ result.i = 0;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = 1;
args[1] = 2;
args[2] = 3;
- result.i = 0;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = 1;
+ args[1].i = 2;
+ args[2].i = 3;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(6, result.i);
+ result.i = 0;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = -1;
args[1] = 2;
args[2] = -3;
- result.i = 0;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = -1;
+ args[1].i = 2;
+ args[2].i = -3;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(-2, result.i);
+ result.i = 1234;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = INT_MAX;
args[1] = INT_MIN;
args[2] = INT_MAX;
- result.i = 1234;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = INT_MAX;
+ args[1].i = INT_MIN;
+ args[2].i = INT_MAX;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(2147483646, result.i);
+ result.i = INT_MIN;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = INT_MAX;
args[1] = INT_MAX;
args[2] = INT_MAX;
- result.i = INT_MIN;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = INT_MAX;
+ args[1].i = INT_MAX;
+ args[2].i = INT_MAX;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(2147483645, result.i);
}
@@ -1139,47 +1237,87 @@
Method::InvokeStub* stub = method->GetInvokeStub();
- int args[4];
JValue result;
-
+ result.i = -1;
+#if !defined(ART_USE_LLVM_COMPILER)
+ int args[4];
args[0] = 0;
args[1] = 0;
args[2] = 0;
args[3] = 0;
- result.i = -1;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ JValue args[4];
+ args[0].i = 0;
+ args[1].i = 0;
+ args[2].i = 0;
+ args[3].i = 0;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(0, result.i);
+ result.i = 0;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = 1;
args[1] = 2;
args[2] = 3;
args[3] = 4;
- result.i = 0;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = 1;
+ args[1].i = 2;
+ args[2].i = 3;
+ args[3].i = 4;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(10, result.i);
+ result.i = 0;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = -1;
args[1] = 2;
args[2] = -3;
args[3] = 4;
- result.i = 0;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = -1;
+ args[1].i = 2;
+ args[2].i = -3;
+ args[3].i = 4;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(2, result.i);
+ result.i = 1234;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = INT_MAX;
args[1] = INT_MIN;
args[2] = INT_MAX;
args[3] = INT_MIN;
- result.i = 1234;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = INT_MAX;
+ args[1].i = INT_MIN;
+ args[2].i = INT_MAX;
+ args[3].i = INT_MIN;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(-2, result.i);
+ result.i = INT_MIN;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = INT_MAX;
args[1] = INT_MAX;
args[2] = INT_MAX;
args[3] = INT_MAX;
- result.i = INT_MIN;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = INT_MAX;
+ args[1].i = INT_MAX;
+ args[2].i = INT_MAX;
+ args[3].i = INT_MAX;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(-4, result.i);
}
@@ -1195,52 +1333,97 @@
Method::InvokeStub* stub = method->GetInvokeStub();
- int args[5];
JValue result;
-
+ result.i = -1.0;
+#if !defined(ART_USE_LLVM_COMPILER)
+ int args[5];
args[0] = 0;
args[1] = 0;
args[2] = 0;
args[3] = 0;
args[4] = 0;
- result.i = -1.0;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ JValue args[5];
+ args[0].i = 0;
+ args[1].i = 0;
+ args[2].i = 0;
+ args[3].i = 0;
+ args[4].i = 0;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(0, result.i);
+ result.i = 0;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = 1;
args[1] = 2;
args[2] = 3;
args[3] = 4;
args[4] = 5;
- result.i = 0;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = 1;
+ args[1].i = 2;
+ args[2].i = 3;
+ args[3].i = 4;
+ args[4].i = 5;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(15, result.i);
+ result.i = 0;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = -1;
args[1] = 2;
args[2] = -3;
args[3] = 4;
args[4] = -5;
- result.i = 0;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = -1;
+ args[1].i = 2;
+ args[2].i = -3;
+ args[3].i = 4;
+ args[4].i = -5;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(-3, result.i);
+ result.i = 1234;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = INT_MAX;
args[1] = INT_MIN;
args[2] = INT_MAX;
args[3] = INT_MIN;
args[4] = INT_MAX;
- result.i = 1234;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = INT_MAX;
+ args[1].i = INT_MIN;
+ args[2].i = INT_MAX;
+ args[3].i = INT_MIN;
+ args[4].i = INT_MAX;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(2147483645, result.i);
+ result.i = INT_MIN;
+#if !defined(ART_USE_LLVM_COMPILER)
args[0] = INT_MAX;
args[1] = INT_MAX;
args[2] = INT_MAX;
args[3] = INT_MAX;
args[4] = INT_MAX;
- result.i = INT_MIN;
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
+#else
+ args[0].i = INT_MAX;
+ args[1].i = INT_MAX;
+ args[2].i = INT_MAX;
+ args[3].i = INT_MAX;
+ args[4].i = INT_MAX;
+ (*stub)(method, NULL, Thread::Current(), CreateArgArray(method, args), &result);
+#endif
EXPECT_EQ(2147483643, result.i);
}
@@ -1409,7 +1592,7 @@
(*stub)(method, NULL, Thread::Current(), reinterpret_cast<byte*>(args), &result);
EXPECT_EQ(3.0, result.d);
}
-#endif // __arm__
+#endif // __arm__ || ART_USE_LLVM_COMPILER
TEST_F(JniInternalTest, Throw) {
EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
diff --git a/src/object.h b/src/object.h
index ca143ac..89b9df4 100644
--- a/src/object.h
+++ b/src/object.h
@@ -755,7 +755,9 @@
void SetFrameSizeInBytes(size_t new_frame_size_in_bytes) {
DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
+#if !defined(ART_USE_LLVM_COMPILER) // LLVM uses shadow stack instead.
DCHECK_LE(static_cast<size_t>(kStackAlignment), new_frame_size_in_bytes);
+#endif
SetField32(OFFSET_OF_OBJECT_MEMBER(Method, frame_size_in_bytes_),
new_frame_size_in_bytes, false);
}