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/base/utils/random-number-generator.h"
     32 #include "src/macro-assembler.h"
     33 #include "src/mips/macro-assembler-mips.h"
     34 #include "src/mips/simulator-mips.h"
     35 #include "src/v8.h"
     36 #include "test/cctest/cctest.h"
     37 
     38 
     39 using namespace v8::internal;
     40 
     41 typedef void* (*F)(int x, int y, int p2, int p3, int p4);
     42 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
     43 
     44 #define __ masm->
     45 
     46 
     47 static byte to_non_zero(int n) {
     48   return static_cast<unsigned>(n) % 255 + 1;
     49 }
     50 
     51 
     52 static bool all_zeroes(const byte* beg, const byte* end) {
     53   CHECK(beg);
     54   CHECK(beg <= end);
     55   while (beg < end) {
     56     if (*beg++ != 0)
     57       return false;
     58   }
     59   return true;
     60 }
     61 
     62 
     63 TEST(CopyBytes) {
     64   CcTest::InitializeVM();
     65   Isolate* isolate = CcTest::i_isolate();
     66   HandleScope handles(isolate);
     67 
     68   const int data_size = 1 * KB;
     69   size_t act_size;
     70 
     71   // Allocate two blocks to copy data between.
     72   byte* src_buffer =
     73       static_cast<byte*>(v8::base::OS::Allocate(data_size, &act_size, 0));
     74   CHECK(src_buffer);
     75   CHECK(act_size >= static_cast<size_t>(data_size));
     76   byte* dest_buffer =
     77       static_cast<byte*>(v8::base::OS::Allocate(data_size, &act_size, 0));
     78   CHECK(dest_buffer);
     79   CHECK(act_size >= static_cast<size_t>(data_size));
     80 
     81   // Storage for a0 and a1.
     82   byte* a0_;
     83   byte* a1_;
     84 
     85   MacroAssembler assembler(isolate, NULL, 0,
     86                            v8::internal::CodeObjectRequired::kYes);
     87   MacroAssembler* masm = &assembler;
     88 
     89   // Code to be generated: The stuff in CopyBytes followed by a store of a0 and
     90   // a1, respectively.
     91   __ CopyBytes(a0, a1, a2, a3);
     92   __ li(a2, Operand(reinterpret_cast<int>(&a0_)));
     93   __ li(a3, Operand(reinterpret_cast<int>(&a1_)));
     94   __ sw(a0, MemOperand(a2));
     95   __ jr(ra);
     96   __ sw(a1, MemOperand(a3));
     97 
     98   CodeDesc desc;
     99   masm->GetCode(&desc);
    100   Handle<Code> code = isolate->factory()->NewCode(
    101       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    102 
    103   ::F f = FUNCTION_CAST< ::F>(code->entry());
    104 
    105   // Initialise source data with non-zero bytes.
    106   for (int i = 0; i < data_size; i++) {
    107     src_buffer[i] = to_non_zero(i);
    108   }
    109 
    110   const int fuzz = 11;
    111 
    112   for (int size = 0; size < 600; size++) {
    113     for (const byte* src = src_buffer; src < src_buffer + fuzz; src++) {
    114       for (byte* dest = dest_buffer; dest < dest_buffer + fuzz; dest++) {
    115         memset(dest_buffer, 0, data_size);
    116         CHECK(dest + size < dest_buffer + data_size);
    117         (void)CALL_GENERATED_CODE(isolate, f, reinterpret_cast<int>(src),
    118                                   reinterpret_cast<int>(dest), size, 0, 0);
    119         // a0 and a1 should point at the first byte after the copied data.
    120         CHECK_EQ(src + size, a0_);
    121         CHECK_EQ(dest + size, a1_);
    122         // Check that we haven't written outside the target area.
    123         CHECK(all_zeroes(dest_buffer, dest));
    124         CHECK(all_zeroes(dest + size, dest_buffer + data_size));
    125         // Check the target area.
    126         CHECK_EQ(0, memcmp(src, dest, size));
    127       }
    128     }
    129   }
    130 
    131   // Check that the source data hasn't been clobbered.
    132   for (int i = 0; i < data_size; i++) {
    133     CHECK(src_buffer[i] == to_non_zero(i));
    134   }
    135 }
    136 
    137 
    138 static void TestNaN(const char *code) {
    139   // NaN value is different on MIPS and x86 architectures, and TEST(NaNx)
    140   // tests checks the case where a x86 NaN value is serialized into the
    141   // snapshot on the simulator during cross compilation.
    142   v8::HandleScope scope(CcTest::isolate());
    143   v8::Local<v8::Context> context = CcTest::NewContext(PRINT_EXTENSION);
    144   v8::Context::Scope context_scope(context);
    145 
    146   v8::Local<v8::Script> script =
    147       v8::Script::Compile(context, v8_str(code)).ToLocalChecked();
    148   v8::Local<v8::Object> result =
    149       v8::Local<v8::Object>::Cast(script->Run(context).ToLocalChecked());
    150   i::Handle<i::JSReceiver> o = v8::Utils::OpenHandle(*result);
    151   i::Handle<i::JSArray> array1(reinterpret_cast<i::JSArray*>(*o));
    152   i::FixedDoubleArray* a = i::FixedDoubleArray::cast(array1->elements());
    153   double value = a->get_scalar(0);
    154   CHECK(std::isnan(value) &&
    155         bit_cast<uint64_t>(value) ==
    156             bit_cast<uint64_t>(std::numeric_limits<double>::quiet_NaN()));
    157 }
    158 
    159 
    160 TEST(NaN0) {
    161   TestNaN(
    162           "var result;"
    163           "for (var i = 0; i < 2; i++) {"
    164           "  result = new Array(Number.NaN, Number.POSITIVE_INFINITY);"
    165           "}"
    166           "result;");
    167 }
    168 
    169 
    170 TEST(NaN1) {
    171   TestNaN(
    172           "var result;"
    173           "for (var i = 0; i < 2; i++) {"
    174           "  result = [NaN];"
    175           "}"
    176           "result;");
    177 }
    178 
    179 
    180 TEST(jump_tables4) {
    181   // Similar to test-assembler-mips jump_tables1, with extra test for branch
    182   // trampoline required before emission of the dd table (where trampolines are
    183   // blocked), and proper transition to long-branch mode.
    184   // Regression test for v8:4294.
    185   CcTest::InitializeVM();
    186   Isolate* isolate = CcTest::i_isolate();
    187   HandleScope scope(isolate);
    188   MacroAssembler assembler(isolate, NULL, 0,
    189                            v8::internal::CodeObjectRequired::kYes);
    190   MacroAssembler* masm = &assembler;
    191 
    192   const int kNumCases = 512;
    193   int values[kNumCases];
    194   isolate->random_number_generator()->NextBytes(values, sizeof(values));
    195   Label labels[kNumCases];
    196   Label near_start, end;
    197 
    198   __ addiu(sp, sp, -4);
    199   __ sw(ra, MemOperand(sp));
    200 
    201   __ mov(v0, zero_reg);
    202 
    203   __ Branch(&end);
    204   __ bind(&near_start);
    205 
    206   // Generate slightly less than 32K instructions, which will soon require
    207   // trampoline for branch distance fixup.
    208   for (int i = 0; i < 32768 - 256; ++i) {
    209     __ addiu(v0, v0, 1);
    210   }
    211 
    212   Label done;
    213   {
    214     __ BlockTrampolinePoolFor(kNumCases + 6);
    215     PredictableCodeSizeScope predictable(
    216         masm, (kNumCases + 6) * Assembler::kInstrSize);
    217     Label here;
    218 
    219     __ bal(&here);
    220     __ sll(at, a0, 2);  // In delay slot.
    221     __ bind(&here);
    222     __ addu(at, at, ra);
    223     __ lw(at, MemOperand(at, 4 * Assembler::kInstrSize));
    224     __ jr(at);
    225     __ nop();  // Branch delay slot nop.
    226     for (int i = 0; i < kNumCases; ++i) {
    227       __ dd(&labels[i]);
    228     }
    229   }
    230 
    231   for (int i = 0; i < kNumCases; ++i) {
    232     __ bind(&labels[i]);
    233     __ lui(v0, (values[i] >> 16) & 0xffff);
    234     __ ori(v0, v0, values[i] & 0xffff);
    235     __ Branch(&done);
    236   }
    237 
    238   __ bind(&done);
    239   __ lw(ra, MemOperand(sp));
    240   __ addiu(sp, sp, 4);
    241   __ jr(ra);
    242   __ nop();
    243 
    244   __ bind(&end);
    245   __ Branch(&near_start);
    246 
    247   CodeDesc desc;
    248   masm->GetCode(&desc);
    249   Handle<Code> code = isolate->factory()->NewCode(
    250       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    251 #ifdef OBJECT_PRINT
    252   code->Print(std::cout);
    253 #endif
    254   F1 f = FUNCTION_CAST<F1>(code->entry());
    255   for (int i = 0; i < kNumCases; ++i) {
    256     int res =
    257         reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
    258     ::printf("f(%d) = %d\n", i, res);
    259     CHECK_EQ(values[i], res);
    260   }
    261 }
    262 
    263 
    264 TEST(jump_tables5) {
    265   if (!IsMipsArchVariant(kMips32r6)) return;
    266 
    267   // Similar to test-assembler-mips jump_tables1, with extra test for emitting a
    268   // compact branch instruction before emission of the dd table.
    269   CcTest::InitializeVM();
    270   Isolate* isolate = CcTest::i_isolate();
    271   HandleScope scope(isolate);
    272   MacroAssembler assembler(isolate, nullptr, 0,
    273                            v8::internal::CodeObjectRequired::kYes);
    274   MacroAssembler* masm = &assembler;
    275 
    276   const int kNumCases = 512;
    277   int values[kNumCases];
    278   isolate->random_number_generator()->NextBytes(values, sizeof(values));
    279   Label labels[kNumCases];
    280   Label done;
    281 
    282   __ addiu(sp, sp, -4);
    283   __ sw(ra, MemOperand(sp));
    284 
    285   {
    286     __ BlockTrampolinePoolFor(kNumCases * 2 + 7 + 1);
    287     PredictableCodeSizeScope predictable(
    288         masm, kNumCases * kPointerSize + ((7 + 1) * Assembler::kInstrSize));
    289     Label here;
    290 
    291     __ bal(&here);
    292     __ sll(at, a0, 2);  // In delay slot.
    293     __ bind(&here);
    294     __ addu(at, at, ra);
    295     __ lw(at, MemOperand(at, 6 * Assembler::kInstrSize));
    296     __ jalr(at);
    297     __ nop();  // Branch delay slot nop.
    298     __ bc(&done);
    299     for (int i = 0; i < kNumCases; ++i) {
    300       __ dd(&labels[i]);
    301     }
    302   }
    303 
    304   for (int i = 0; i < kNumCases; ++i) {
    305     __ bind(&labels[i]);
    306     __ lui(v0, (values[i] >> 16) & 0xffff);
    307     __ ori(v0, v0, values[i] & 0xffff);
    308     __ jr(ra);
    309     __ nop();
    310   }
    311 
    312   __ bind(&done);
    313   __ lw(ra, MemOperand(sp));
    314   __ addiu(sp, sp, 4);
    315   __ jr(ra);
    316   __ nop();
    317 
    318   CodeDesc desc;
    319   masm->GetCode(&desc);
    320   Handle<Code> code = isolate->factory()->NewCode(
    321       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    322 #ifdef OBJECT_PRINT
    323   code->Print(std::cout);
    324 #endif
    325   F1 f = FUNCTION_CAST<F1>(code->entry());
    326   for (int i = 0; i < kNumCases; ++i) {
    327     int32_t res = reinterpret_cast<int32_t>(
    328         CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
    329     ::printf("f(%d) = %d\n", i, res);
    330     CHECK_EQ(values[i], res);
    331   }
    332 }
    333 
    334 
    335 static uint32_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) {
    336   Isolate* isolate = CcTest::i_isolate();
    337   HandleScope scope(isolate);
    338   MacroAssembler assembler(isolate, nullptr, 0,
    339                            v8::internal::CodeObjectRequired::kYes);
    340   MacroAssembler* masm = &assembler;
    341 
    342   __ Lsa(v0, a0, a1, sa);
    343   __ jr(ra);
    344   __ nop();
    345 
    346   CodeDesc desc;
    347   assembler.GetCode(&desc);
    348   Handle<Code> code = isolate->factory()->NewCode(
    349       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    350 
    351   F1 f = FUNCTION_CAST<F1>(code->entry());
    352 
    353   uint32_t res = reinterpret_cast<uint32_t>(
    354       CALL_GENERATED_CODE(isolate, f, rt, rs, 0, 0, 0));
    355 
    356   return res;
    357 }
    358 
    359 
    360 TEST(Lsa) {
    361   CcTest::InitializeVM();
    362   struct TestCaseLsa {
    363     int32_t rt;
    364     int32_t rs;
    365     uint8_t sa;
    366     uint32_t expected_res;
    367   };
    368 
    369   struct TestCaseLsa tc[] = {// rt, rs, sa, expected_res
    370                              {0x4, 0x1, 1, 0x6},
    371                              {0x4, 0x1, 2, 0x8},
    372                              {0x4, 0x1, 3, 0xc},
    373                              {0x4, 0x1, 4, 0x14},
    374                              {0x4, 0x1, 5, 0x24},
    375                              {0x0, 0x1, 1, 0x2},
    376                              {0x0, 0x1, 2, 0x4},
    377                              {0x0, 0x1, 3, 0x8},
    378                              {0x0, 0x1, 4, 0x10},
    379                              {0x0, 0x1, 5, 0x20},
    380                              {0x4, 0x0, 1, 0x4},
    381                              {0x4, 0x0, 2, 0x4},
    382                              {0x4, 0x0, 3, 0x4},
    383                              {0x4, 0x0, 4, 0x4},
    384                              {0x4, 0x0, 5, 0x4},
    385 
    386                              // Shift overflow.
    387                              {0x4, INT32_MAX, 1, 0x2},
    388                              {0x4, INT32_MAX >> 1, 2, 0x0},
    389                              {0x4, INT32_MAX >> 2, 3, 0xfffffffc},
    390                              {0x4, INT32_MAX >> 3, 4, 0xfffffff4},
    391                              {0x4, INT32_MAX >> 4, 5, 0xffffffe4},
    392 
    393                              // Signed addition overflow.
    394                              {INT32_MAX - 1, 0x1, 1, 0x80000000},
    395                              {INT32_MAX - 3, 0x1, 2, 0x80000000},
    396                              {INT32_MAX - 7, 0x1, 3, 0x80000000},
    397                              {INT32_MAX - 15, 0x1, 4, 0x80000000},
    398                              {INT32_MAX - 31, 0x1, 5, 0x80000000},
    399 
    400                              // Addition overflow.
    401                              {-2, 0x1, 1, 0x0},
    402                              {-4, 0x1, 2, 0x0},
    403                              {-8, 0x1, 3, 0x0},
    404                              {-16, 0x1, 4, 0x0},
    405                              {-32, 0x1, 5, 0x0}};
    406 
    407   size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLsa);
    408   for (size_t i = 0; i < nr_test_cases; ++i) {
    409     uint32_t res = run_lsa(tc[i].rt, tc[i].rs, tc[i].sa);
    410     PrintF("0x%x =? 0x%x == lsa(v0, %x, %x, %hhu)\n", tc[i].expected_res, res,
    411            tc[i].rt, tc[i].rs, tc[i].sa);
    412     CHECK_EQ(tc[i].expected_res, res);
    413   }
    414 }
    415 
    416 #undef __
    417