Home | History | Annotate | Download | only in cctest
      1 // Copyright 2006-2008 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 "v8.h"
     31 
     32 #include "disassembler.h"
     33 #include "factory.h"
     34 #include "macro-assembler.h"
     35 #include "platform.h"
     36 #include "serialize.h"
     37 #include "cctest.h"
     38 
     39 using namespace v8::internal;
     40 
     41 
     42 typedef int (*F0)();
     43 typedef int (*F1)(int x);
     44 typedef int (*F2)(int x, int y);
     45 
     46 
     47 static v8::Persistent<v8::Context> env;
     48 
     49 
     50 static void InitializeVM() {
     51   if (env.IsEmpty()) {
     52     env = v8::Context::New();
     53   }
     54 }
     55 
     56 
     57 #define __ assm.
     58 
     59 TEST(AssemblerIa320) {
     60   InitializeVM();
     61   v8::HandleScope scope;
     62 
     63   v8::internal::byte buffer[256];
     64   Assembler assm(buffer, sizeof buffer);
     65 
     66   __ mov(eax, Operand(esp, 4));
     67   __ add(eax, Operand(esp, 8));
     68   __ ret(0);
     69 
     70   CodeDesc desc;
     71   assm.GetCode(&desc);
     72   Object* code = Heap::CreateCode(desc,
     73                                   NULL,
     74                                   Code::ComputeFlags(Code::STUB),
     75                                   Handle<Object>(Heap::undefined_value()));
     76   CHECK(code->IsCode());
     77 #ifdef DEBUG
     78   Code::cast(code)->Print();
     79 #endif
     80   F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
     81   int res = f(3, 4);
     82   ::printf("f() = %d\n", res);
     83   CHECK_EQ(7, res);
     84 }
     85 
     86 
     87 TEST(AssemblerIa321) {
     88   InitializeVM();
     89   v8::HandleScope scope;
     90 
     91   v8::internal::byte buffer[256];
     92   Assembler assm(buffer, sizeof buffer);
     93   Label L, C;
     94 
     95   __ mov(edx, Operand(esp, 4));
     96   __ xor_(eax, Operand(eax));  // clear eax
     97   __ jmp(&C);
     98 
     99   __ bind(&L);
    100   __ add(eax, Operand(edx));
    101   __ sub(Operand(edx), Immediate(1));
    102 
    103   __ bind(&C);
    104   __ test(edx, Operand(edx));
    105   __ j(not_zero, &L, taken);
    106   __ ret(0);
    107 
    108   CodeDesc desc;
    109   assm.GetCode(&desc);
    110   Object* code = Heap::CreateCode(desc,
    111                                   NULL,
    112                                   Code::ComputeFlags(Code::STUB),
    113                                   Handle<Object>(Heap::undefined_value()));
    114   CHECK(code->IsCode());
    115 #ifdef DEBUG
    116   Code::cast(code)->Print();
    117 #endif
    118   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
    119   int res = f(100);
    120   ::printf("f() = %d\n", res);
    121   CHECK_EQ(5050, res);
    122 }
    123 
    124 
    125 TEST(AssemblerIa322) {
    126   InitializeVM();
    127   v8::HandleScope scope;
    128 
    129   v8::internal::byte buffer[256];
    130   Assembler assm(buffer, sizeof buffer);
    131   Label L, C;
    132 
    133   __ mov(edx, Operand(esp, 4));
    134   __ mov(eax, 1);
    135   __ jmp(&C);
    136 
    137   __ bind(&L);
    138   __ imul(eax, Operand(edx));
    139   __ sub(Operand(edx), Immediate(1));
    140 
    141   __ bind(&C);
    142   __ test(edx, Operand(edx));
    143   __ j(not_zero, &L, taken);
    144   __ ret(0);
    145 
    146   // some relocated stuff here, not executed
    147   __ mov(eax, Factory::true_value());
    148   __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
    149 
    150   CodeDesc desc;
    151   assm.GetCode(&desc);
    152   Object* code = Heap::CreateCode(desc,
    153                                   NULL,
    154                                   Code::ComputeFlags(Code::STUB),
    155                                   Handle<Object>(Heap::undefined_value()));
    156   CHECK(code->IsCode());
    157 #ifdef DEBUG
    158   Code::cast(code)->Print();
    159 #endif
    160   F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
    161   int res = f(10);
    162   ::printf("f() = %d\n", res);
    163   CHECK_EQ(3628800, res);
    164 }
    165 
    166 
    167 typedef int (*F3)(float x);
    168 
    169 TEST(AssemblerIa323) {
    170   InitializeVM();
    171   v8::HandleScope scope;
    172 
    173   v8::internal::byte buffer[256];
    174   Assembler assm(buffer, sizeof buffer);
    175 
    176   CHECK(CpuFeatures::IsSupported(SSE2));
    177   { CpuFeatures::Scope fscope(SSE2);
    178     __ cvttss2si(eax, Operand(esp, 4));
    179     __ ret(0);
    180   }
    181 
    182   CodeDesc desc;
    183   assm.GetCode(&desc);
    184   Code* code =
    185       Code::cast(Heap::CreateCode(desc,
    186                                   NULL,
    187                                   Code::ComputeFlags(Code::STUB),
    188                                   Handle<Object>(Heap::undefined_value())));
    189   // don't print the code - our disassembler can't handle cvttss2si
    190   // instead print bytes
    191   Disassembler::Dump(stdout,
    192                      code->instruction_start(),
    193                      code->instruction_start() + code->instruction_size());
    194   F3 f = FUNCTION_CAST<F3>(code->entry());
    195   int res = f(static_cast<float>(-3.1415));
    196   ::printf("f() = %d\n", res);
    197   CHECK_EQ(-3, res);
    198 }
    199 
    200 
    201 typedef int (*F4)(double x);
    202 
    203 TEST(AssemblerIa324) {
    204   InitializeVM();
    205   v8::HandleScope scope;
    206 
    207   v8::internal::byte buffer[256];
    208   Assembler assm(buffer, sizeof buffer);
    209 
    210   CHECK(CpuFeatures::IsSupported(SSE2));
    211   CpuFeatures::Scope fscope(SSE2);
    212   __ cvttsd2si(eax, Operand(esp, 4));
    213   __ ret(0);
    214 
    215   CodeDesc desc;
    216   assm.GetCode(&desc);
    217   Code* code =
    218       Code::cast(Heap::CreateCode(desc,
    219                                   NULL,
    220                                   Code::ComputeFlags(Code::STUB),
    221                                   Handle<Object>(Heap::undefined_value())));
    222   // don't print the code - our disassembler can't handle cvttsd2si
    223   // instead print bytes
    224   Disassembler::Dump(stdout,
    225                      code->instruction_start(),
    226                      code->instruction_start() + code->instruction_size());
    227   F4 f = FUNCTION_CAST<F4>(code->entry());
    228   int res = f(2.718281828);
    229   ::printf("f() = %d\n", res);
    230   CHECK_EQ(2, res);
    231 }
    232 
    233 
    234 static int baz = 42;
    235 TEST(AssemblerIa325) {
    236   InitializeVM();
    237   v8::HandleScope scope;
    238 
    239   v8::internal::byte buffer[256];
    240   Assembler assm(buffer, sizeof buffer);
    241 
    242   __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE));
    243   __ ret(0);
    244 
    245   CodeDesc desc;
    246   assm.GetCode(&desc);
    247   Code* code =
    248       Code::cast(Heap::CreateCode(desc,
    249                                   NULL,
    250                                   Code::ComputeFlags(Code::STUB),
    251                                   Handle<Object>(Heap::undefined_value())));
    252   F0 f = FUNCTION_CAST<F0>(code->entry());
    253   int res = f();
    254   CHECK_EQ(42, res);
    255 }
    256 
    257 
    258 typedef double (*F5)(double x, double y);
    259 
    260 TEST(AssemblerIa326) {
    261   InitializeVM();
    262   v8::HandleScope scope;
    263   CHECK(CpuFeatures::IsSupported(SSE2));
    264   CpuFeatures::Scope fscope(SSE2);
    265   v8::internal::byte buffer[256];
    266   Assembler assm(buffer, sizeof buffer);
    267 
    268   __ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
    269   __ movdbl(xmm1, Operand(esp, 3 * kPointerSize));
    270   __ addsd(xmm0, xmm1);
    271   __ mulsd(xmm0, xmm1);
    272   __ subsd(xmm0, xmm1);
    273   __ divsd(xmm0, xmm1);
    274   // Copy xmm0 to st(0) using eight bytes of stack.
    275   __ sub(Operand(esp), Immediate(8));
    276   __ movdbl(Operand(esp, 0), xmm0);
    277   __ fld_d(Operand(esp, 0));
    278   __ add(Operand(esp), Immediate(8));
    279   __ ret(0);
    280 
    281   CodeDesc desc;
    282   assm.GetCode(&desc);
    283   Code* code =
    284       Code::cast(Heap::CreateCode(desc,
    285                                   NULL,
    286                                   Code::ComputeFlags(Code::STUB),
    287                                   Handle<Object>(Heap::undefined_value())));
    288 #ifdef DEBUG
    289   ::printf("\n---\n");
    290   // don't print the code - our disassembler can't handle SSE instructions
    291   // instead print bytes
    292   Disassembler::Dump(stdout,
    293                      code->instruction_start(),
    294                      code->instruction_start() + code->instruction_size());
    295 #endif
    296   F5 f = FUNCTION_CAST<F5>(code->entry());
    297   double res = f(2.2, 1.1);
    298   ::printf("f() = %f\n", res);
    299   CHECK(2.29 < res && res < 2.31);
    300 }
    301 
    302 
    303 typedef double (*F6)(int x);
    304 
    305 TEST(AssemblerIa328) {
    306   InitializeVM();
    307   v8::HandleScope scope;
    308   CHECK(CpuFeatures::IsSupported(SSE2));
    309   CpuFeatures::Scope fscope(SSE2);
    310   v8::internal::byte buffer[256];
    311   Assembler assm(buffer, sizeof buffer);
    312   __ mov(eax, Operand(esp, 4));
    313   __ cvtsi2sd(xmm0, Operand(eax));
    314   // Copy xmm0 to st(0) using eight bytes of stack.
    315   __ sub(Operand(esp), Immediate(8));
    316   __ movdbl(Operand(esp, 0), xmm0);
    317   __ fld_d(Operand(esp, 0));
    318   __ add(Operand(esp), Immediate(8));
    319   __ ret(0);
    320   CodeDesc desc;
    321   assm.GetCode(&desc);
    322   Code* code =
    323       Code::cast(Heap::CreateCode(desc,
    324                                   NULL,
    325                                   Code::ComputeFlags(Code::STUB),
    326                                   Handle<Object>(Heap::undefined_value())));
    327   CHECK(code->IsCode());
    328 #ifdef DEBUG
    329   Code::cast(code)->Print();
    330 #endif
    331   F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
    332   double res = f(12);
    333 
    334   ::printf("f() = %f\n", res);
    335   CHECK(11.99 < res && res < 12.001);
    336 }
    337 
    338 
    339 typedef int (*F7)(double x, double y);
    340 
    341 TEST(AssemblerIa329) {
    342   InitializeVM();
    343   v8::HandleScope scope;
    344   v8::internal::byte buffer[256];
    345   MacroAssembler assm(buffer, sizeof buffer);
    346   enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
    347   Label equal_l, less_l, greater_l, nan_l;
    348   __ fld_d(Operand(esp, 3 * kPointerSize));
    349   __ fld_d(Operand(esp, 1 * kPointerSize));
    350   __ FCmp();
    351   __ j(parity_even, &nan_l, taken);
    352   __ j(equal, &equal_l, taken);
    353   __ j(below, &less_l, taken);
    354   __ j(above, &greater_l, taken);
    355 
    356   __ mov(eax, kUndefined);
    357   __ ret(0);
    358 
    359   __ bind(&equal_l);
    360   __ mov(eax, kEqual);
    361   __ ret(0);
    362 
    363   __ bind(&greater_l);
    364   __ mov(eax, kGreater);
    365   __ ret(0);
    366 
    367   __ bind(&less_l);
    368   __ mov(eax, kLess);
    369   __ ret(0);
    370 
    371   __ bind(&nan_l);
    372   __ mov(eax, kNaN);
    373   __ ret(0);
    374 
    375 
    376   CodeDesc desc;
    377   assm.GetCode(&desc);
    378   Code* code =
    379       Code::cast(Heap::CreateCode(desc,
    380                                   NULL,
    381                                   Code::ComputeFlags(Code::STUB),
    382                                   Handle<Object>(Heap::undefined_value())));
    383   CHECK(code->IsCode());
    384 #ifdef DEBUG
    385   Code::cast(code)->Print();
    386 #endif
    387 
    388   F7 f = FUNCTION_CAST<F7>(Code::cast(code)->entry());
    389   CHECK_EQ(kLess, f(1.1, 2.2));
    390   CHECK_EQ(kEqual, f(2.2, 2.2));
    391   CHECK_EQ(kGreater, f(3.3, 2.2));
    392   CHECK_EQ(kNaN, f(OS::nan_value(), 1.1));
    393 }
    394 
    395 #undef __
    396