Home | History | Annotate | Download | only in cctest
      1 // Copyright 2011 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 
     30 #include "src/v8.h"
     31 
     32 #include "src/base/platform/platform.h"
     33 #include "src/base/utils/random-number-generator.h"
     34 #include "src/disassembler.h"
     35 #include "src/factory.h"
     36 #include "src/macro-assembler.h"
     37 #include "src/ostreams.h"
     38 #include "test/cctest/cctest.h"
     39 
     40 using namespace v8::internal;
     41 
     42 
     43 typedef int (*F0)();
     44 typedef int (*F1)(int x);
     45 typedef int (*F2)(int x, int y);
     46 
     47 
     48 #define __ assm.
     49 
     50 TEST(AssemblerIa320) {
     51   CcTest::InitializeVM();
     52   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
     53   HandleScope scope(isolate);
     54 
     55   v8::internal::byte buffer[256];
     56   Assembler assm(isolate, buffer, sizeof buffer);
     57 
     58   __ mov(eax, Operand(esp, 4));
     59   __ add(eax, Operand(esp, 8));
     60   __ ret(0);
     61 
     62   CodeDesc desc;
     63   assm.GetCode(&desc);
     64   Handle<Code> code = isolate->factory()->NewCode(
     65       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
     66 #ifdef OBJECT_PRINT
     67   OFStream os(stdout);
     68   code->Print(os);
     69 #endif
     70   F2 f = FUNCTION_CAST<F2>(code->entry());
     71   int res = f(3, 4);
     72   ::printf("f() = %d\n", res);
     73   CHECK_EQ(7, res);
     74 }
     75 
     76 
     77 TEST(AssemblerIa321) {
     78   CcTest::InitializeVM();
     79   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
     80   HandleScope scope(isolate);
     81 
     82   v8::internal::byte buffer[256];
     83   Assembler assm(isolate, buffer, sizeof buffer);
     84   Label L, C;
     85 
     86   __ mov(edx, Operand(esp, 4));
     87   __ xor_(eax, eax);  // clear eax
     88   __ jmp(&C);
     89 
     90   __ bind(&L);
     91   __ add(eax, edx);
     92   __ sub(edx, Immediate(1));
     93 
     94   __ bind(&C);
     95   __ test(edx, edx);
     96   __ j(not_zero, &L);
     97   __ ret(0);
     98 
     99   CodeDesc desc;
    100   assm.GetCode(&desc);
    101   Handle<Code> code = isolate->factory()->NewCode(
    102       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    103 #ifdef OBJECT_PRINT
    104   OFStream os(stdout);
    105   code->Print(os);
    106 #endif
    107   F1 f = FUNCTION_CAST<F1>(code->entry());
    108   int res = f(100);
    109   ::printf("f() = %d\n", res);
    110   CHECK_EQ(5050, res);
    111 }
    112 
    113 
    114 TEST(AssemblerIa322) {
    115   CcTest::InitializeVM();
    116   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
    117   HandleScope scope(isolate);
    118 
    119   v8::internal::byte buffer[256];
    120   Assembler assm(isolate, buffer, sizeof buffer);
    121   Label L, C;
    122 
    123   __ mov(edx, Operand(esp, 4));
    124   __ mov(eax, 1);
    125   __ jmp(&C);
    126 
    127   __ bind(&L);
    128   __ imul(eax, edx);
    129   __ sub(edx, Immediate(1));
    130 
    131   __ bind(&C);
    132   __ test(edx, edx);
    133   __ j(not_zero, &L);
    134   __ ret(0);
    135 
    136   // some relocated stuff here, not executed
    137   __ mov(eax, isolate->factory()->true_value());
    138   __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
    139 
    140   CodeDesc desc;
    141   assm.GetCode(&desc);
    142   Handle<Code> code = isolate->factory()->NewCode(
    143       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    144 #ifdef OBJECT_PRINT
    145   OFStream os(stdout);
    146   code->Print(os);
    147 #endif
    148   F1 f = FUNCTION_CAST<F1>(code->entry());
    149   int res = f(10);
    150   ::printf("f() = %d\n", res);
    151   CHECK_EQ(3628800, res);
    152 }
    153 
    154 
    155 typedef int (*F3)(float x);
    156 
    157 typedef int (*F4)(double x);
    158 
    159 static int baz = 42;
    160 TEST(AssemblerIa325) {
    161   CcTest::InitializeVM();
    162   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
    163   HandleScope scope(isolate);
    164 
    165   v8::internal::byte buffer[256];
    166   Assembler assm(isolate, buffer, sizeof buffer);
    167 
    168   __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
    169   __ ret(0);
    170 
    171   CodeDesc desc;
    172   assm.GetCode(&desc);
    173   Handle<Code> code = isolate->factory()->NewCode(
    174       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    175   F0 f = FUNCTION_CAST<F0>(code->entry());
    176   int res = f();
    177   CHECK_EQ(42, res);
    178 }
    179 
    180 
    181 typedef int (*F7)(double x, double y);
    182 
    183 TEST(AssemblerIa329) {
    184   CcTest::InitializeVM();
    185   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
    186   HandleScope scope(isolate);
    187   v8::internal::byte buffer[256];
    188   MacroAssembler assm(isolate, buffer, sizeof(buffer),
    189                       v8::internal::CodeObjectRequired::kYes);
    190   enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
    191   Label equal_l, less_l, greater_l, nan_l;
    192   __ fld_d(Operand(esp, 3 * kPointerSize));
    193   __ fld_d(Operand(esp, 1 * kPointerSize));
    194   __ FCmp();
    195   __ j(parity_even, &nan_l);
    196   __ j(equal, &equal_l);
    197   __ j(below, &less_l);
    198   __ j(above, &greater_l);
    199 
    200   __ mov(eax, kUndefined);
    201   __ ret(0);
    202 
    203   __ bind(&equal_l);
    204   __ mov(eax, kEqual);
    205   __ ret(0);
    206 
    207   __ bind(&greater_l);
    208   __ mov(eax, kGreater);
    209   __ ret(0);
    210 
    211   __ bind(&less_l);
    212   __ mov(eax, kLess);
    213   __ ret(0);
    214 
    215   __ bind(&nan_l);
    216   __ mov(eax, kNaN);
    217   __ ret(0);
    218 
    219 
    220   CodeDesc desc;
    221   assm.GetCode(&desc);
    222   Handle<Code> code = isolate->factory()->NewCode(
    223       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    224 #ifdef OBJECT_PRINT
    225   OFStream os(stdout);
    226   code->Print(os);
    227 #endif
    228 
    229   F7 f = FUNCTION_CAST<F7>(code->entry());
    230   CHECK_EQ(kLess, f(1.1, 2.2));
    231   CHECK_EQ(kEqual, f(2.2, 2.2));
    232   CHECK_EQ(kGreater, f(3.3, 2.2));
    233   CHECK_EQ(kNaN, f(std::numeric_limits<double>::quiet_NaN(), 1.1));
    234 }
    235 
    236 
    237 TEST(AssemblerIa3210) {
    238   // Test chaining of label usages within instructions (issue 1644).
    239   CcTest::InitializeVM();
    240   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
    241   HandleScope scope(isolate);
    242   Assembler assm(isolate, NULL, 0);
    243 
    244   Label target;
    245   __ j(equal, &target);
    246   __ j(not_equal, &target);
    247   __ bind(&target);
    248   __ nop();
    249 }
    250 
    251 
    252 TEST(AssemblerMultiByteNop) {
    253   CcTest::InitializeVM();
    254   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
    255   HandleScope scope(isolate);
    256   v8::internal::byte buffer[1024];
    257   Assembler assm(isolate, buffer, sizeof(buffer));
    258   __ push(ebx);
    259   __ push(ecx);
    260   __ push(edx);
    261   __ push(edi);
    262   __ push(esi);
    263   __ mov(eax, 1);
    264   __ mov(ebx, 2);
    265   __ mov(ecx, 3);
    266   __ mov(edx, 4);
    267   __ mov(edi, 5);
    268   __ mov(esi, 6);
    269   for (int i = 0; i < 16; i++) {
    270     int before = assm.pc_offset();
    271     __ Nop(i);
    272     CHECK_EQ(assm.pc_offset() - before, i);
    273   }
    274 
    275   Label fail;
    276   __ cmp(eax, 1);
    277   __ j(not_equal, &fail);
    278   __ cmp(ebx, 2);
    279   __ j(not_equal, &fail);
    280   __ cmp(ecx, 3);
    281   __ j(not_equal, &fail);
    282   __ cmp(edx, 4);
    283   __ j(not_equal, &fail);
    284   __ cmp(edi, 5);
    285   __ j(not_equal, &fail);
    286   __ cmp(esi, 6);
    287   __ j(not_equal, &fail);
    288   __ mov(eax, 42);
    289   __ pop(esi);
    290   __ pop(edi);
    291   __ pop(edx);
    292   __ pop(ecx);
    293   __ pop(ebx);
    294   __ ret(0);
    295   __ bind(&fail);
    296   __ mov(eax, 13);
    297   __ pop(esi);
    298   __ pop(edi);
    299   __ pop(edx);
    300   __ pop(ecx);
    301   __ pop(ebx);
    302   __ ret(0);
    303 
    304   CodeDesc desc;
    305   assm.GetCode(&desc);
    306   Handle<Code> code = isolate->factory()->NewCode(
    307       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    308   CHECK(code->IsCode());
    309 
    310   F0 f = FUNCTION_CAST<F0>(code->entry());
    311   int res = f();
    312   CHECK_EQ(42, res);
    313 }
    314 
    315 
    316 TEST(AssemblerIa32JumpTables1) {
    317   // Test jump tables with forward jumps.
    318   CcTest::InitializeVM();
    319   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
    320   HandleScope scope(isolate);
    321   Assembler assm(isolate, nullptr, 0);
    322 
    323   const int kNumCases = 512;
    324   int values[kNumCases];
    325   isolate->random_number_generator()->NextBytes(values, sizeof(values));
    326   Label labels[kNumCases];
    327 
    328   Label done, table;
    329   __ mov(eax, Operand(esp, 4));
    330   __ jmp(Operand::JumpTable(eax, times_4, &table));
    331   __ ud2();
    332   __ bind(&table);
    333   for (int i = 0; i < kNumCases; ++i) {
    334     __ dd(&labels[i]);
    335   }
    336 
    337   for (int i = 0; i < kNumCases; ++i) {
    338     __ bind(&labels[i]);
    339     __ mov(eax, Immediate(values[i]));
    340     __ jmp(&done);
    341   }
    342 
    343   __ bind(&done);
    344   __ ret(0);
    345 
    346   CodeDesc desc;
    347   assm.GetCode(&desc);
    348   Handle<Code> code = isolate->factory()->NewCode(
    349       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    350 #ifdef OBJECT_PRINT
    351   OFStream os(stdout);
    352   code->Print(os);
    353 #endif
    354   F1 f = FUNCTION_CAST<F1>(code->entry());
    355   for (int i = 0; i < kNumCases; ++i) {
    356     int res = f(i);
    357     ::printf("f(%d) = %d\n", i, res);
    358     CHECK_EQ(values[i], res);
    359   }
    360 }
    361 
    362 
    363 TEST(AssemblerIa32JumpTables2) {
    364   // Test jump tables with backward jumps.
    365   CcTest::InitializeVM();
    366   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
    367   HandleScope scope(isolate);
    368   Assembler assm(isolate, nullptr, 0);
    369 
    370   const int kNumCases = 512;
    371   int values[kNumCases];
    372   isolate->random_number_generator()->NextBytes(values, sizeof(values));
    373   Label labels[kNumCases];
    374 
    375   Label done, table;
    376   __ mov(eax, Operand(esp, 4));
    377   __ jmp(Operand::JumpTable(eax, times_4, &table));
    378   __ ud2();
    379 
    380   for (int i = 0; i < kNumCases; ++i) {
    381     __ bind(&labels[i]);
    382     __ mov(eax, Immediate(values[i]));
    383     __ jmp(&done);
    384   }
    385 
    386   __ bind(&table);
    387   for (int i = 0; i < kNumCases; ++i) {
    388     __ dd(&labels[i]);
    389   }
    390 
    391   __ bind(&done);
    392   __ ret(0);
    393 
    394   CodeDesc desc;
    395   assm.GetCode(&desc);
    396   Handle<Code> code = isolate->factory()->NewCode(
    397       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
    398 #ifdef OBJECT_PRINT
    399   OFStream os(stdout);
    400   code->Print(os);
    401 #endif
    402   F1 f = FUNCTION_CAST<F1>(code->entry());
    403   for (int i = 0; i < kNumCases; ++i) {
    404     int res = f(i);
    405     ::printf("f(%d) = %d\n", i, res);
    406     CHECK_EQ(values[i], res);
    407   }
    408 }
    409 
    410 #undef __
    411