From eac59b81ff376f97ea282da66641a65964fb39c8 Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Mon, 23 Sep 2013 08:06:58 +0000 Subject: [PATCH] Fixed a bug in CopyBytes() and new test cases for ARM macro assembler TEST=cctest/test-macro-assembler-arm R=bmeurer@chromium.org Review URL: https://codereview.chromium.org/23447035 Patch from Bangfu Tao . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16873 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/macro-assembler-arm.cc | 11 +- test/cctest/cctest.gyp | 3 +- test/cctest/test-macro-assembler-arm.cc | 136 ++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 7 deletions(-) create mode 100644 test/cctest/test-macro-assembler-arm.cc diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 42018472c3..eeabc053f5 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -3291,20 +3291,19 @@ void MacroAssembler::CopyBytes(Register src, Register dst, Register length, Register scratch) { - Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done; + Label align_loop_1, word_loop, byte_loop, byte_loop_1, done; // Align src before copying in word size chunks. - bind(&align_loop); - cmp(length, Operand::Zero()); - b(eq, &done); + cmp(length, Operand(kPointerSize)); + b(le, &byte_loop); + bind(&align_loop_1); tst(src, Operand(kPointerSize - 1)); b(eq, &word_loop); ldrb(scratch, MemOperand(src, 1, PostIndex)); strb(scratch, MemOperand(dst, 1, PostIndex)); sub(length, length, Operand(1), SetCC); - b(ne, &byte_loop_1); - + b(&align_loop_1); // Copy bytes in word size chunks. bind(&word_loop); if (emit_debug_code()) { diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp index ee7ffad6d3..8c6bf95d0e 100644 --- a/test/cctest/cctest.gyp +++ b/test/cctest/cctest.gyp @@ -139,7 +139,8 @@ 'test-assembler-arm.cc', 'test-code-stubs.cc', 'test-code-stubs-arm.cc', - 'test-disasm-arm.cc' + 'test-disasm-arm.cc', + 'test-macro-assembler-arm.cc' ], }], ['v8_target_arch=="mipsel"', { diff --git a/test/cctest/test-macro-assembler-arm.cc b/test/cctest/test-macro-assembler-arm.cc new file mode 100644 index 0000000000..77f7abbd44 --- /dev/null +++ b/test/cctest/test-macro-assembler-arm.cc @@ -0,0 +1,136 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "v8.h" +#include "macro-assembler.h" +#include "arm/macro-assembler-arm.h" +#include "arm/simulator-arm.h" +#include "cctest.h" + + +using namespace v8::internal; + +typedef void* (*F)(int x, int y, int p2, int p3, int p4); + +#define __ masm-> + + +static byte to_non_zero(int n) { + return static_cast(n) % 255 + 1; +} + + +static bool all_zeroes(const byte* beg, const byte* end) { + CHECK(beg); + CHECK(beg <= end); + while (beg < end) { + if (*beg++ != 0) + return false; + } + return true; +} + + +TEST(CopyBytes) { + CcTest::InitializeVM(); + Isolate* isolate = Isolate::Current(); + HandleScope handles(isolate); + + const int data_size = 1 * KB; + size_t act_size; + + // Allocate two blocks to copy data between. + byte* src_buffer = static_cast(OS::Allocate(data_size, &act_size, 0)); + CHECK(src_buffer); + CHECK(act_size >= static_cast(data_size)); + byte* dest_buffer = static_cast(OS::Allocate(data_size, &act_size, 0)); + CHECK(dest_buffer); + CHECK(act_size >= static_cast(data_size)); + + // Storage for R0 and R1. + byte* r0_; + byte* r1_; + + MacroAssembler assembler(isolate, NULL, 0); + MacroAssembler* masm = &assembler; + + // Code to be generated: The stuff in CopyBytes followed by a store of R0 and + // R1, respectively. + __ CopyBytes(r0, r1, r2, r3); + __ mov(r2, Operand(reinterpret_cast(&r0_))); + __ mov(r3, Operand(reinterpret_cast(&r1_))); + __ str(r0, MemOperand(r2)); + __ str(r1, MemOperand(r3)); + __ bx(lr); + + CodeDesc desc; + masm->GetCode(&desc); + Object* code = isolate->heap()->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle())->ToObjectChecked(); + CHECK(code->IsCode()); + + F f = FUNCTION_CAST(Code::cast(code)->entry()); + + // Initialise source data with non-zero bytes. + for (int i = 0; i < data_size; i++) { + src_buffer[i] = to_non_zero(i); + } + + const int fuzz = 11; + + for (int size = 0; size < 600; size++) { + for (const byte* src = src_buffer; src < src_buffer + fuzz; src++) { + for (byte* dest = dest_buffer; dest < dest_buffer + fuzz; dest++) { + memset(dest_buffer, 0, data_size); + CHECK(dest + size < dest_buffer + data_size); + (void) CALL_GENERATED_CODE(f, reinterpret_cast(src), + reinterpret_cast(dest), size, 0, 0); + // R0 and R1 should point at the first byte after the copied data. + CHECK_EQ(src + size, r0_); + CHECK_EQ(dest + size, r1_); + // Check that we haven't written outside the target area. + CHECK(all_zeroes(dest_buffer, dest)); + CHECK(all_zeroes(dest + size, dest_buffer + data_size)); + // Check the target area. + CHECK_EQ(0, memcmp(src, dest, size)); + } + } + } + + // Check that the source data hasn't been clobbered. + for (int i = 0; i < data_size; i++) { + CHECK(src_buffer[i] == to_non_zero(i)); + } +} + + + +#undef __