Home | History | Annotate | Download | only in cctest
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <stdlib.h>
     29 #include <iostream>  // NOLINT(readability/streams)
     30 
     31 #include "src/v8.h"
     32 #include "test/cctest/cctest.h"
     33 
     34 #include "src/base/utils/random-number-generator.h"
     35 #include "src/macro-assembler.h"
     36 #include "src/mips64/macro-assembler-mips64.h"
     37 #include "src/mips64/simulator-mips64.h"
     38 
     39 
     40 using namespace v8::internal;
     41 
     42 typedef void* (*F)(int64_t x, int64_t y, int p2, int p3, int p4);
     43 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
     44 
     45 #define __ masm->
     46 
     47 
     48 static byte to_non_zero(int n) {
     49   return static_cast<unsigned>(n) % 255 + 1;
     50 }
     51 
     52 
     53 static bool all_zeroes(const byte* beg, const byte* end) {
     54   CHECK(beg);
     55   CHECK(beg <= end);
     56   while (beg < end) {
     57     if (*beg++ != 0)
     58       return false;
     59   }
     60   return true;
     61 }
     62 
     63 
     64 TEST(CopyBytes) {
     65   CcTest::InitializeVM();
     66   Isolate* isolate = CcTest::i_isolate();
     67   HandleScope handles(isolate);
     68 
     69   const int data_size = 1 * KB;
     70   size_t act_size;
     71 
     72   // Allocate two blocks to copy data between.
     73   byte* src_buffer =
     74       static_cast<byte*>(v8::base::OS::Allocate(data_size, &act_size, 0));
     75   CHECK(src_buffer);
     76   CHECK(act_size >= static_cast<size_t>(data_size));
     77   byte* dest_buffer =
     78       static_cast<byte*>(v8::base::OS::Allocate(data_size, &act_size, 0));
     79   CHECK(dest_buffer);
     80   CHECK(act_size >= static_cast<size_t>(data_size));
     81 
     82   // Storage for a0 and a1.
     83   byte* a0_;
     84   byte* a1_;
     85 
     86   MacroAssembler assembler(isolate, NULL, 0,
     87                            v8::internal::CodeObjectRequired::kYes);
     88   MacroAssembler* masm = &assembler;
     89 
     90   // Code to be generated: The stuff in CopyBytes followed by a store of a0 and
     91   // a1, respectively.
     92   __ CopyBytes(a0, a1, a2, a3);
     93   __ li(a2, Operand(reinterpret_cast<int64_t>(&a0_)));
     94   __ li(a3, Operand(reinterpret_cast<int64_t>(&a1_)));
     95   __ sd(a0, MemOperand(a2));
     96   __ jr(ra);
     97   __ sd(a1, MemOperand(a3));
     98 
     99   CodeDesc desc;
    100   masm->GetCode(&desc);
    101   Handle<Code> code = isolate->factory()->NewCode(
    102       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    103 
    104   ::F f = FUNCTION_CAST< ::F>(code->entry());
    105 
    106   // Initialise source data with non-zero bytes.
    107   for (int i = 0; i < data_size; i++) {
    108     src_buffer[i] = to_non_zero(i);
    109   }
    110 
    111   const int fuzz = 11;
    112 
    113   for (int size = 0; size < 600; size++) {
    114     for (const byte* src = src_buffer; src < src_buffer + fuzz; src++) {
    115       for (byte* dest = dest_buffer; dest < dest_buffer + fuzz; dest++) {
    116         memset(dest_buffer, 0, data_size);
    117         CHECK(dest + size < dest_buffer + data_size);
    118         (void)CALL_GENERATED_CODE(isolate, f, reinterpret_cast<int64_t>(src),
    119                                   reinterpret_cast<int64_t>(dest), size, 0, 0);
    120         // a0 and a1 should point at the first byte after the copied data.
    121         CHECK_EQ(src + size, a0_);
    122         CHECK_EQ(dest + size, a1_);
    123         // Check that we haven't written outside the target area.
    124         CHECK(all_zeroes(dest_buffer, dest));
    125         CHECK(all_zeroes(dest + size, dest_buffer + data_size));
    126         // Check the target area.
    127         CHECK_EQ(0, memcmp(src, dest, size));
    128       }
    129     }
    130   }
    131 
    132   // Check that the source data hasn't been clobbered.
    133   for (int i = 0; i < data_size; i++) {
    134     CHECK(src_buffer[i] == to_non_zero(i));
    135   }
    136 }
    137 
    138 
    139 TEST(LoadConstants) {
    140   CcTest::InitializeVM();
    141   Isolate* isolate = CcTest::i_isolate();
    142   HandleScope handles(isolate);
    143 
    144   int64_t refConstants[64];
    145   int64_t result[64];
    146 
    147   int64_t mask = 1;
    148   for (int i = 0; i < 64; i++) {
    149     refConstants[i] = ~(mask << i);
    150   }
    151 
    152   MacroAssembler assembler(isolate, NULL, 0,
    153                            v8::internal::CodeObjectRequired::kYes);
    154   MacroAssembler* masm = &assembler;
    155 
    156   __ mov(a4, a0);
    157   for (int i = 0; i < 64; i++) {
    158     // Load constant.
    159     __ li(a5, Operand(refConstants[i]));
    160     __ sd(a5, MemOperand(a4));
    161     __ Daddu(a4, a4, Operand(kPointerSize));
    162   }
    163 
    164   __ jr(ra);
    165   __ nop();
    166 
    167   CodeDesc desc;
    168   masm->GetCode(&desc);
    169   Handle<Code> code = isolate->factory()->NewCode(
    170       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    171 
    172   ::F f = FUNCTION_CAST< ::F>(code->entry());
    173   (void)CALL_GENERATED_CODE(isolate, f, reinterpret_cast<int64_t>(result), 0, 0,
    174                             0, 0);
    175   // Check results.
    176   for (int i = 0; i < 64; i++) {
    177     CHECK(refConstants[i] == result[i]);
    178   }
    179 }
    180 
    181 
    182 TEST(LoadAddress) {
    183   CcTest::InitializeVM();
    184   Isolate* isolate = CcTest::i_isolate();
    185   HandleScope handles(isolate);
    186 
    187   MacroAssembler assembler(isolate, NULL, 0,
    188                            v8::internal::CodeObjectRequired::kYes);
    189   MacroAssembler* masm = &assembler;
    190   Label to_jump, skip;
    191   __ mov(a4, a0);
    192 
    193   __ Branch(&skip);
    194   __ bind(&to_jump);
    195   __ nop();
    196   __ nop();
    197   __ jr(ra);
    198   __ nop();
    199   __ bind(&skip);
    200   __ li(a4, Operand(masm->jump_address(&to_jump)), ADDRESS_LOAD);
    201   int check_size = masm->InstructionsGeneratedSince(&skip);
    202   CHECK_EQ(check_size, 4);
    203   __ jr(a4);
    204   __ nop();
    205   __ stop("invalid");
    206   __ stop("invalid");
    207   __ stop("invalid");
    208   __ stop("invalid");
    209   __ stop("invalid");
    210 
    211 
    212   CodeDesc desc;
    213   masm->GetCode(&desc);
    214   Handle<Code> code = isolate->factory()->NewCode(
    215       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    216 
    217   ::F f = FUNCTION_CAST< ::F>(code->entry());
    218   (void)CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0);
    219   // Check results.
    220 }
    221 
    222 
    223 TEST(jump_tables4) {
    224   // Similar to test-assembler-mips jump_tables1, with extra test for branch
    225   // trampoline required before emission of the dd table (where trampolines are
    226   // blocked), and proper transition to long-branch mode.
    227   // Regression test for v8:4294.
    228   CcTest::InitializeVM();
    229   Isolate* isolate = CcTest::i_isolate();
    230   HandleScope scope(isolate);
    231   MacroAssembler assembler(isolate, NULL, 0,
    232                            v8::internal::CodeObjectRequired::kYes);
    233   MacroAssembler* masm = &assembler;
    234 
    235   const int kNumCases = 512;
    236   int values[kNumCases];
    237   isolate->random_number_generator()->NextBytes(values, sizeof(values));
    238   Label labels[kNumCases];
    239   Label near_start, end;
    240 
    241   __ daddiu(sp, sp, -8);
    242   __ sd(ra, MemOperand(sp));
    243 
    244   __ mov(v0, zero_reg);
    245 
    246   __ Branch(&end);
    247   __ bind(&near_start);
    248 
    249   // Generate slightly less than 32K instructions, which will soon require
    250   // trampoline for branch distance fixup.
    251   for (int i = 0; i < 32768 - 256; ++i) {
    252     __ addiu(v0, v0, 1);
    253   }
    254 
    255   __ Align(8);
    256   Label done;
    257   {
    258     __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
    259     PredictableCodeSizeScope predictable(
    260         masm, (kNumCases * 2 + 6) * Assembler::kInstrSize);
    261     Label here;
    262 
    263     __ bal(&here);
    264     __ dsll(at, a0, 3);  // In delay slot.
    265     __ bind(&here);
    266     __ daddu(at, at, ra);
    267     __ ld(at, MemOperand(at, 4 * Assembler::kInstrSize));
    268     __ jr(at);
    269     __ nop();  // Branch delay slot nop.
    270     for (int i = 0; i < kNumCases; ++i) {
    271       __ dd(&labels[i]);
    272     }
    273   }
    274 
    275   for (int i = 0; i < kNumCases; ++i) {
    276     __ bind(&labels[i]);
    277     __ lui(v0, (values[i] >> 16) & 0xffff);
    278     __ ori(v0, v0, values[i] & 0xffff);
    279     __ Branch(&done);
    280   }
    281 
    282   __ bind(&done);
    283   __ ld(ra, MemOperand(sp));
    284   __ daddiu(sp, sp, 8);
    285   __ jr(ra);
    286   __ nop();
    287 
    288   __ bind(&end);
    289   __ Branch(&near_start);
    290 
    291   CodeDesc desc;
    292   masm->GetCode(&desc);
    293   Handle<Code> code = isolate->factory()->NewCode(
    294       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    295 #ifdef OBJECT_PRINT
    296   code->Print(std::cout);
    297 #endif
    298   F1 f = FUNCTION_CAST<F1>(code->entry());
    299   for (int i = 0; i < kNumCases; ++i) {
    300     int64_t res = reinterpret_cast<int64_t>(
    301         CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
    302     ::printf("f(%d) = %" PRId64 "\n", i, res);
    303     CHECK_EQ(values[i], res);
    304   }
    305 }
    306 
    307 
    308 TEST(jump_tables5) {
    309   if (kArchVariant != kMips64r6) return;
    310 
    311   // Similar to test-assembler-mips jump_tables1, with extra test for emitting a
    312   // compact branch instruction before emission of the dd table.
    313   CcTest::InitializeVM();
    314   Isolate* isolate = CcTest::i_isolate();
    315   HandleScope scope(isolate);
    316   MacroAssembler assembler(isolate, nullptr, 0,
    317                            v8::internal::CodeObjectRequired::kYes);
    318   MacroAssembler* masm = &assembler;
    319 
    320   const int kNumCases = 512;
    321   int values[kNumCases];
    322   isolate->random_number_generator()->NextBytes(values, sizeof(values));
    323   Label labels[kNumCases];
    324   Label done;
    325 
    326   __ daddiu(sp, sp, -8);
    327   __ sd(ra, MemOperand(sp));
    328 
    329   __ Align(8);
    330   {
    331     __ BlockTrampolinePoolFor(kNumCases * 2 + 7 + 1);
    332     PredictableCodeSizeScope predictable(
    333         masm, kNumCases * kPointerSize + ((7 + 1) * Assembler::kInstrSize));
    334     Label here;
    335 
    336     __ bal(&here);
    337     __ dsll(at, a0, 3);  // In delay slot.
    338     __ bind(&here);
    339     __ daddu(at, at, ra);
    340     __ ld(at, MemOperand(at, 6 * Assembler::kInstrSize));
    341     __ jalr(at);
    342     __ nop();  // Branch delay slot nop.
    343     __ bc(&done);
    344     // A nop instruction must be generated by the forbidden slot guard
    345     // (Assembler::dd(Label*)) so the first label goes to an 8 bytes aligned
    346     // location.
    347     for (int i = 0; i < kNumCases; ++i) {
    348       __ dd(&labels[i]);
    349     }
    350   }
    351 
    352   for (int i = 0; i < kNumCases; ++i) {
    353     __ bind(&labels[i]);
    354     __ lui(v0, (values[i] >> 16) & 0xffff);
    355     __ ori(v0, v0, values[i] & 0xffff);
    356     __ jr(ra);
    357     __ nop();
    358   }
    359 
    360   __ bind(&done);
    361   __ ld(ra, MemOperand(sp));
    362   __ daddiu(sp, sp, 8);
    363   __ jr(ra);
    364   __ nop();
    365 
    366   CodeDesc desc;
    367   masm->GetCode(&desc);
    368   Handle<Code> code = isolate->factory()->NewCode(
    369       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    370 #ifdef OBJECT_PRINT
    371   code->Print(std::cout);
    372 #endif
    373   F1 f = FUNCTION_CAST<F1>(code->entry());
    374   for (int i = 0; i < kNumCases; ++i) {
    375     int64_t res = reinterpret_cast<int64_t>(
    376         CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
    377     ::printf("f(%d) = %" PRId64 "\n", i, res);
    378     CHECK_EQ(values[i], res);
    379   }
    380 }
    381 
    382 
    383 static uint64_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) {
    384   Isolate* isolate = CcTest::i_isolate();
    385   HandleScope scope(isolate);
    386   MacroAssembler assembler(isolate, nullptr, 0,
    387                            v8::internal::CodeObjectRequired::kYes);
    388   MacroAssembler* masm = &assembler;
    389 
    390   __ Lsa(v0, a0, a1, sa);
    391   __ jr(ra);
    392   __ nop();
    393 
    394   CodeDesc desc;
    395   assembler.GetCode(&desc);
    396   Handle<Code> code = isolate->factory()->NewCode(
    397       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    398 
    399   F1 f = FUNCTION_CAST<F1>(code->entry());
    400 
    401   uint64_t res = reinterpret_cast<uint64_t>(
    402       CALL_GENERATED_CODE(isolate, f, rt, rs, 0, 0, 0));
    403 
    404   return res;
    405 }
    406 
    407 
    408 TEST(Lsa) {
    409   CcTest::InitializeVM();
    410   struct TestCaseLsa {
    411     int32_t rt;
    412     int32_t rs;
    413     uint8_t sa;
    414     uint64_t expected_res;
    415   };
    416 
    417   struct TestCaseLsa tc[] = {// rt, rs, sa, expected_res
    418                              {0x4, 0x1, 1, 0x6},
    419                              {0x4, 0x1, 2, 0x8},
    420                              {0x4, 0x1, 3, 0xc},
    421                              {0x4, 0x1, 4, 0x14},
    422                              {0x4, 0x1, 5, 0x24},
    423                              {0x0, 0x1, 1, 0x2},
    424                              {0x0, 0x1, 2, 0x4},
    425                              {0x0, 0x1, 3, 0x8},
    426                              {0x0, 0x1, 4, 0x10},
    427                              {0x0, 0x1, 5, 0x20},
    428                              {0x4, 0x0, 1, 0x4},
    429                              {0x4, 0x0, 2, 0x4},
    430                              {0x4, 0x0, 3, 0x4},
    431                              {0x4, 0x0, 4, 0x4},
    432                              {0x4, 0x0, 5, 0x4},
    433 
    434                              // Shift overflow.
    435                              {0x4, INT32_MAX, 1, 0x2},
    436                              {0x4, INT32_MAX >> 1, 2, 0x0},
    437                              {0x4, INT32_MAX >> 2, 3, 0xfffffffffffffffc},
    438                              {0x4, INT32_MAX >> 3, 4, 0xfffffffffffffff4},
    439                              {0x4, INT32_MAX >> 4, 5, 0xffffffffffffffe4},
    440 
    441                              // Signed addition overflow.
    442                              {INT32_MAX - 1, 0x1, 1, 0xffffffff80000000},
    443                              {INT32_MAX - 3, 0x1, 2, 0xffffffff80000000},
    444                              {INT32_MAX - 7, 0x1, 3, 0xffffffff80000000},
    445                              {INT32_MAX - 15, 0x1, 4, 0xffffffff80000000},
    446                              {INT32_MAX - 31, 0x1, 5, 0xffffffff80000000},
    447 
    448                              // Addition overflow.
    449                              {-2, 0x1, 1, 0x0},
    450                              {-4, 0x1, 2, 0x0},
    451                              {-8, 0x1, 3, 0x0},
    452                              {-16, 0x1, 4, 0x0},
    453                              {-32, 0x1, 5, 0x0}};
    454 
    455   size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLsa);
    456   for (size_t i = 0; i < nr_test_cases; ++i) {
    457     uint64_t res = run_lsa(tc[i].rt, tc[i].rs, tc[i].sa);
    458     PrintF("0x%" PRIx64 " =? 0x%" PRIx64 " == Lsa(v0, %x, %x, %hhu)\n",
    459            tc[i].expected_res, res, tc[i].rt, tc[i].rs, tc[i].sa);
    460     CHECK_EQ(tc[i].expected_res, res);
    461   }
    462 }
    463 
    464 
    465 static uint64_t run_dlsa(uint64_t rt, uint64_t rs, int8_t sa) {
    466   Isolate* isolate = CcTest::i_isolate();
    467   HandleScope scope(isolate);
    468   MacroAssembler assembler(isolate, nullptr, 0,
    469                            v8::internal::CodeObjectRequired::kYes);
    470   MacroAssembler* masm = &assembler;
    471 
    472   __ Dlsa(v0, a0, a1, sa);
    473   __ jr(ra);
    474   __ nop();
    475 
    476   CodeDesc desc;
    477   assembler.GetCode(&desc);
    478   Handle<Code> code = isolate->factory()->NewCode(
    479       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    480 
    481   ::F f = FUNCTION_CAST<::F>(code->entry());
    482 
    483   uint64_t res = reinterpret_cast<uint64_t>(
    484       CALL_GENERATED_CODE(isolate, f, rt, rs, 0, 0, 0));
    485 
    486   return res;
    487 }
    488 
    489 
    490 TEST(Dlsa) {
    491   CcTest::InitializeVM();
    492   struct TestCaseLsa {
    493     int64_t rt;
    494     int64_t rs;
    495     uint8_t sa;
    496     uint64_t expected_res;
    497   };
    498 
    499   struct TestCaseLsa tc[] = {// rt, rs, sa, expected_res
    500                              {0x4, 0x1, 1, 0x6},
    501                              {0x4, 0x1, 2, 0x8},
    502                              {0x4, 0x1, 3, 0xc},
    503                              {0x4, 0x1, 4, 0x14},
    504                              {0x4, 0x1, 5, 0x24},
    505                              {0x0, 0x1, 1, 0x2},
    506                              {0x0, 0x1, 2, 0x4},
    507                              {0x0, 0x1, 3, 0x8},
    508                              {0x0, 0x1, 4, 0x10},
    509                              {0x0, 0x1, 5, 0x20},
    510                              {0x4, 0x0, 1, 0x4},
    511                              {0x4, 0x0, 2, 0x4},
    512                              {0x4, 0x0, 3, 0x4},
    513                              {0x4, 0x0, 4, 0x4},
    514                              {0x4, 0x0, 5, 0x4},
    515 
    516                              // Shift overflow.
    517                              {0x4, INT64_MAX, 1, 0x2},
    518                              {0x4, INT64_MAX >> 1, 2, 0x0},
    519                              {0x4, INT64_MAX >> 2, 3, 0xfffffffffffffffc},
    520                              {0x4, INT64_MAX >> 3, 4, 0xfffffffffffffff4},
    521                              {0x4, INT64_MAX >> 4, 5, 0xffffffffffffffe4},
    522 
    523                              // Signed addition overflow.
    524                              {INT64_MAX - 1, 0x1, 1, 0x8000000000000000},
    525                              {INT64_MAX - 3, 0x1, 2, 0x8000000000000000},
    526                              {INT64_MAX - 7, 0x1, 3, 0x8000000000000000},
    527                              {INT64_MAX - 15, 0x1, 4, 0x8000000000000000},
    528                              {INT64_MAX - 31, 0x1, 5, 0x8000000000000000},
    529 
    530                              // Addition overflow.
    531                              {-2, 0x1, 1, 0x0},
    532                              {-4, 0x1, 2, 0x0},
    533                              {-8, 0x1, 3, 0x0},
    534                              {-16, 0x1, 4, 0x0},
    535                              {-32, 0x1, 5, 0x0}};
    536 
    537   size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLsa);
    538   for (size_t i = 0; i < nr_test_cases; ++i) {
    539     uint64_t res = run_dlsa(tc[i].rt, tc[i].rs, tc[i].sa);
    540     PrintF("0x%" PRIx64 " =? 0x%" PRIx64 " == Dlsa(v0, %" PRIx64 ", %" PRIx64
    541            ", %hhu)\n",
    542            tc[i].expected_res, res, tc[i].rt, tc[i].rs, tc[i].sa);
    543     CHECK_EQ(tc[i].expected_res, res);
    544   }
    545 }
    546 
    547 #undef __
    548