Index: test/cctest/test-macro-assembler-x64.cc |
diff --git a/test/cctest/test-macro-assembler-x64.cc b/test/cctest/test-macro-assembler-x64.cc |
index 612f9e88a3d96e5808064a037707f1f0b88c3eb9..128c8a8871e17f712bc201843085e3b85e7f8ea3 100644 |
--- a/test/cctest/test-macro-assembler-x64.cc |
+++ b/test/cctest/test-macro-assembler-x64.cc |
@@ -33,6 +33,7 @@ |
#include "src/factory.h" |
#include "src/macro-assembler.h" |
#include "test/cctest/cctest.h" |
+#include "test/cctest/heap/heap-utils.h" |
namespace i = v8::internal; |
using i::Address; |
@@ -91,6 +92,7 @@ using i::times_pointer_size; |
// with GCC. A different convention is used on 64-bit windows. |
typedef int (*F0)(); |
+typedef intptr_t (*F1)(); |
#define __ masm-> |
@@ -2728,5 +2730,197 @@ TEST(LoadAndStoreWithRepresentation) { |
CHECK_EQ(0, result); |
} |
+// Helper for the tests below. |
+template <typename Fun> |
+void AssembleFunction(Isolate* isolate, size_t actual_size, byte* buffer, |
+ Fun f) { |
+ MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size), |
+ v8::internal::CodeObjectRequired::kYes); |
+ MacroAssembler* masm = &assembler; |
+ Label exit; |
+ EntryCode(masm); |
+ f(masm); |
+ ExitCode(masm); |
+ __ ret(0); |
+ |
+ CodeDesc desc; |
+ masm->GetCode(&desc); |
+} |
+ |
+TEST(AllocateMacrosNoGCRequired) { |
+ // Allocate an executable page of memory. |
+ size_t actual_size; |
+ byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
+ Assembler::kMinimalBufferSize, &actual_size, true)); |
+ CHECK(buffer); |
+ Isolate* isolate = CcTest::i_isolate(); |
+ HandleScope handles(isolate); |
+ |
+ AllocationFlags const kDoubleAligned = |
+ static_cast<AllocationFlags>(DOUBLE_ALIGNMENT); |
+ AllocationFlags const kNoAllocationFlags = |
+ static_cast<AllocationFlags>(NO_ALLOCATION_FLAGS); |
+ |
+#define CHECK_TAGGED(result) CHECK_EQ(result& i::kHeapObjectTag, 1); |
+#define CHECK_DOUBLE_ALIGNED(result) \ |
+ do { \ |
+ CHECK_TAGGED((result)); \ |
+ CHECK_EQ((result)&i::kDoubleAlignmentMaskTagged, 0); \ |
+ } while (false) |
+ |
+ i::heap::GcAndSweep(isolate->heap(), i::AllocationSpace::NEW_SPACE); |
+ { |
+ AssembleFunction(isolate, actual_size, buffer, [](MacroAssembler* masm) { |
+ Label gc_required, success; |
+ __ Allocate(kPointerSize, rax, rcx, rdx, &gc_required, |
+ kNoAllocationFlags); |
+ __ jmp(&success); |
+ __ bind(&gc_required); |
+ __ Abort(i::kNoReason); |
+ __ bind(&success); |
+ }); |
+ intptr_t test_result = FUNCTION_CAST<F1>(buffer)(); |
+ CHECK_TAGGED(test_result); |
+ } |
+ |
+ { |
+ AssembleFunction(isolate, actual_size, buffer, [](MacroAssembler* masm) { |
+ Label gc_required, success; |
+ __ Allocate(i::kDoubleSize, rax, rcx, rdx, &gc_required, kDoubleAligned); |
+ __ jmp(&success); |
+ __ bind(&gc_required); |
+ __ Abort(i::kNoReason); |
+ __ bind(&success); |
+ }); |
+ i::heap::MakeSureNewSpaceTopIsNotDoubleAligned(isolate->heap()); |
+ intptr_t test_result = FUNCTION_CAST<F1>(buffer)(); |
+ CHECK_DOUBLE_ALIGNED(test_result); |
+ } |
+ { |
+ AssembleFunction(isolate, actual_size, buffer, [](MacroAssembler* masm) { |
+ Label gc_required, success; |
+ __ movl(rbx, Immediate(kPointerSize)); |
+ __ Allocate(kPointerSize, rax, rcx, rdx, &gc_required, |
+ kNoAllocationFlags); |
+ __ jmp(&success); |
+ __ bind(&gc_required); |
+ __ Abort(i::kNoReason); |
+ __ bind(&success); |
+ }); |
+ intptr_t test_result = FUNCTION_CAST<F1>(buffer)(); |
+ CHECK_TAGGED(test_result); |
+ } |
+ |
+ { |
+ AssembleFunction(isolate, actual_size, buffer, [](MacroAssembler* masm) { |
+ Label gc_required, success; |
+ __ movl(rbx, Immediate(i::kDoubleSize)); |
+ __ Allocate(rbx, rax, rcx, rdx, &gc_required, kDoubleAligned); |
+ __ jmp(&success); |
+ __ bind(&gc_required); |
+ __ Abort(i::kNoReason); |
+ __ bind(&success); |
+ }); |
+ i::heap::MakeSureNewSpaceTopIsNotDoubleAligned(isolate->heap()); |
+ intptr_t test_result = FUNCTION_CAST<F1>(buffer)(); |
+ CHECK_DOUBLE_ALIGNED(test_result); |
+ } |
+ |
+ { |
+ AssembleFunction(isolate, actual_size, buffer, [](MacroAssembler* masm) { |
+ Label gc_required, success; |
+ __ movl(rbx, Immediate(2)); |
+ __ Allocate(0, i::times_4, rbx, rax, rcx, rdx, &gc_required, |
+ kNoAllocationFlags); |
+ __ jmp(&success); |
+ __ bind(&gc_required); |
+ __ Abort(i::kNoReason); |
+ __ bind(&success); |
+ }); |
+ intptr_t test_result = FUNCTION_CAST<F1>(buffer)(); |
+ CHECK_TAGGED(test_result); |
+ } |
+ |
+ { |
+ AssembleFunction(isolate, actual_size, buffer, [](MacroAssembler* masm) { |
+ Label gc_required, success; |
+ __ movl(rbx, Immediate(i::kDoubleSize)); |
+ __ Allocate(i::FixedDoubleArray::kHeaderSize, i::times_8, rbx, rax, rcx, |
+ rdx, &gc_required, kDoubleAligned); |
+ __ jmp(&success); |
+ __ bind(&gc_required); |
+ __ Abort(i::kNoReason); |
+ __ bind(&success); |
+ }); |
+ i::heap::MakeSureNewSpaceTopIsNotDoubleAligned(isolate->heap()); |
+ intptr_t test_result = FUNCTION_CAST<F1>(buffer)(); |
+ CHECK_DOUBLE_ALIGNED(test_result); |
+ } |
+#undef CHECK_TAGGED |
+#undef CHECK_DOUBLE_ALIGNED |
+} |
+ |
+TEST(AllocateMacrosGCRequired) { |
+ // Allocate an executable page of memory. |
+ size_t actual_size; |
+ byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
+ Assembler::kMinimalBufferSize, &actual_size, true)); |
+ CHECK(buffer); |
+ Isolate* isolate = CcTest::i_isolate(); |
+ HandleScope handles(isolate); |
+ |
+ AllocationFlags const kDoubleAligned = |
+ static_cast<AllocationFlags>(DOUBLE_ALIGNMENT); |
+ |
+ // Test that the macro jumps to the gc_required label if there's not enough |
+ // space to allocate with double alignment. |
+ { |
+ AssembleFunction(isolate, actual_size, buffer, [](MacroAssembler* masm) { |
+ Label gc_required, end; |
+ __ Allocate(kPointerSize, rax, rcx, rdx, &gc_required, kDoubleAligned); |
+ __ xorl(rax, rax); |
+ __ jmp(&end); |
+ __ bind(&gc_required); |
+ __ movl(rax, Immediate(1)); |
+ __ bind(&end); |
+ }); |
+ i::heap::AllocateAllButNBytes(isolate->heap()->new_space(), 4); |
+ intptr_t test_result = FUNCTION_CAST<F1>(buffer)(); |
+ CHECK_EQ(test_result, 1); |
+ } |
+ |
+ { |
+ AssembleFunction(isolate, actual_size, buffer, [](MacroAssembler* masm) { |
+ Label gc_required, end; |
+ __ movl(rbx, Immediate(kPointerSize)); |
+ __ Allocate(rbx, rax, rcx, rdx, &gc_required, kDoubleAligned); |
+ __ xorl(rax, rax); |
+ __ jmp(&end); |
+ __ bind(&gc_required); |
+ __ movl(rax, Immediate(1)); |
+ __ bind(&end); |
+ }); |
+ i::heap::AllocateAllButNBytes(isolate->heap()->new_space(), 4); |
+ intptr_t test_result = FUNCTION_CAST<F1>(buffer)(); |
+ CHECK_EQ(test_result, 1); |
+ } |
+ |
+ { |
+ AssembleFunction(isolate, actual_size, buffer, [](MacroAssembler* masm) { |
+ Label gc_required, end; |
+ __ movl(rbx, Immediate(kPointerSize)); |
+ __ Allocate(0, i::times_8, rbx, rax, rcx, rdx, &gc_required, |
+ kDoubleAligned); |
+ __ xorl(rax, rax); |
+ __ jmp(&end); |
+ __ bind(&gc_required); |
+ __ movl(rax, Immediate(1)); |
+ __ bind(&end); |
+ }); |
+ i::heap::AllocateAllButNBytes(isolate->heap()->new_space(), 4); |
+ intptr_t test_result = FUNCTION_CAST<F1>(buffer)(); |
+ CHECK_EQ(test_result, 1); |
+ } |
+} |
#undef __ |