OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <math.h> |
| 6 #include <stdint.h> |
| 7 #include <stdlib.h> |
| 8 #include <string.h> |
| 9 |
| 10 #include "src/compiler/ffi-compiler.h" |
| 11 |
| 12 #include "test/cctest/cctest.h" |
| 13 |
| 14 using namespace v8::base; |
| 15 using namespace v8::internal; |
| 16 using namespace v8::internal::compiler; |
| 17 |
| 18 static int foo() { |
| 19 printf("hello world from native code\n"); |
| 20 return 42; |
| 21 } |
| 22 |
| 23 TEST(Run_FFI_Hello) { |
| 24 Isolate* isolate = CcTest::InitIsolateOnce(); |
| 25 HandleScope scope(isolate); |
| 26 |
| 27 Handle<String> name = isolate->factory()->InternalizeUtf8String("foo"); |
| 28 Handle<Object> undefined = isolate->factory()->undefined_value(); |
| 29 |
| 30 MachineType reps[] = {MachineType::Int32()}; |
| 31 static v8::internal::MachineSignature sig_foo(1, 0, reps); |
| 32 v8::internal::ffi::NativeFunction func = {&sig_foo, |
| 33 reinterpret_cast<uint8_t*>(foo)}; |
| 34 |
| 35 Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func); |
| 36 |
| 37 Handle<Object> result = |
| 38 Execution::Call(isolate, jsfunc, undefined, 0, nullptr).ToHandleChecked(); |
| 39 |
| 40 CHECK_EQ(42.0, result->Number()); |
| 41 } |
| 42 |
| 43 static int add2(int x, int y) { return x + y; } |
| 44 |
| 45 TEST(Run_FFI_add2) { |
| 46 Isolate* isolate = CcTest::InitIsolateOnce(); |
| 47 HandleScope scope(isolate); |
| 48 |
| 49 Handle<String> name = isolate->factory()->InternalizeUtf8String("add2"); |
| 50 Handle<Object> undefined = isolate->factory()->undefined_value(); |
| 51 |
| 52 MachineType reps[] = {MachineType::Int32(), MachineType::Int32(), |
| 53 MachineType::Int32()}; |
| 54 static v8::internal::MachineSignature sig(1, 2, reps); |
| 55 v8::internal::ffi::NativeFunction func = {&sig, |
| 56 reinterpret_cast<uint8_t*>(add2)}; |
| 57 |
| 58 Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func); |
| 59 |
| 60 // Simple math should work. |
| 61 { |
| 62 Handle<Object> args[] = {isolate->factory()->NewNumber(1.0), |
| 63 isolate->factory()->NewNumber(41.0)}; |
| 64 Handle<Object> result = |
| 65 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 66 .ToHandleChecked(); |
| 67 CHECK_EQ(42.0, result->Number()); |
| 68 } |
| 69 |
| 70 // Truncate floating point to integer. |
| 71 { |
| 72 Handle<Object> args[] = {isolate->factory()->NewNumber(1.9), |
| 73 isolate->factory()->NewNumber(41.0)}; |
| 74 Handle<Object> result = |
| 75 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 76 .ToHandleChecked(); |
| 77 CHECK_EQ(42.0, result->Number()); |
| 78 } |
| 79 |
| 80 // INT_MAX + 1 should wrap. |
| 81 { |
| 82 Handle<Object> args[] = {isolate->factory()->NewNumber(kMaxInt), |
| 83 isolate->factory()->NewNumber(1)}; |
| 84 Handle<Object> result = |
| 85 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 86 .ToHandleChecked(); |
| 87 CHECK_EQ(kMinInt, result->Number()); |
| 88 } |
| 89 |
| 90 // INT_MIN + -1 should wrap. |
| 91 { |
| 92 Handle<Object> args[] = {isolate->factory()->NewNumber(kMinInt), |
| 93 isolate->factory()->NewNumber(-1)}; |
| 94 Handle<Object> result = |
| 95 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 96 .ToHandleChecked(); |
| 97 CHECK_EQ(kMaxInt, result->Number()); |
| 98 } |
| 99 |
| 100 // Numbers get truncated to the 32 least significant bits. |
| 101 { |
| 102 Handle<Object> args[] = {isolate->factory()->NewNumber(1ull << 40), |
| 103 isolate->factory()->NewNumber(-1)}; |
| 104 Handle<Object> result = |
| 105 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 106 .ToHandleChecked(); |
| 107 CHECK_EQ(-1, result->Number()); |
| 108 } |
| 109 |
| 110 // String '57' converts to 57. |
| 111 { |
| 112 Handle<Object> args[] = { |
| 113 isolate->factory()->NewStringFromAsciiChecked("57"), |
| 114 isolate->factory()->NewNumber(41.0)}; |
| 115 Handle<Object> result = |
| 116 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 117 .ToHandleChecked(); |
| 118 CHECK_EQ(98.0, result->Number()); |
| 119 } |
| 120 |
| 121 // String 'foo' converts to 0. |
| 122 // TODO(ofrobots): should this throw instead? |
| 123 { |
| 124 Handle<Object> args[] = { |
| 125 isolate->factory()->NewStringFromAsciiChecked("foo"), |
| 126 isolate->factory()->NewNumber(41.0)}; |
| 127 Handle<Object> result = |
| 128 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 129 .ToHandleChecked(); |
| 130 CHECK_EQ(41.0, result->Number()); |
| 131 } |
| 132 |
| 133 // String '58o' converts to 0. |
| 134 // TODO(ofrobots): should this throw instead? |
| 135 { |
| 136 Handle<Object> args[] = { |
| 137 isolate->factory()->NewStringFromAsciiChecked("58o"), |
| 138 isolate->factory()->NewNumber(41.0)}; |
| 139 Handle<Object> result = |
| 140 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 141 .ToHandleChecked(); |
| 142 CHECK_EQ(41.0, result->Number()); |
| 143 } |
| 144 |
| 145 // NaN converts to 0. |
| 146 // TODO(ofrobots): should this throw instead? |
| 147 { |
| 148 Handle<Object> args[] = {isolate->factory()->nan_value(), |
| 149 isolate->factory()->NewNumber(41.0)}; |
| 150 Handle<Object> result = |
| 151 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 152 .ToHandleChecked(); |
| 153 CHECK_EQ(41.0, result->Number()); |
| 154 } |
| 155 |
| 156 // null converts to 0. |
| 157 // TODO(ofrobots): should this throw instead? |
| 158 { |
| 159 Handle<Object> args[] = {isolate->factory()->null_value(), |
| 160 isolate->factory()->NewNumber(41.0)}; |
| 161 Handle<Object> result = |
| 162 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 163 .ToHandleChecked(); |
| 164 CHECK_EQ(41.0, result->Number()); |
| 165 } |
| 166 } |
| 167 |
| 168 static int add7(int x1, int x2, int x3, int x4, int x5, int x6, int x7) { |
| 169 return x1 + x2 + x3 + x4 + x5 + x6 + x7; |
| 170 } |
| 171 |
| 172 TEST(Run_FFI_add7) { |
| 173 Isolate* isolate = CcTest::InitIsolateOnce(); |
| 174 HandleScope scope(isolate); |
| 175 |
| 176 Handle<String> name = isolate->factory()->InternalizeUtf8String("add7"); |
| 177 Handle<Object> undefined = isolate->factory()->undefined_value(); |
| 178 |
| 179 MachineType reps[] = {MachineType::Int32(), MachineType::Int32(), |
| 180 MachineType::Int32(), MachineType::Int32(), |
| 181 MachineType::Int32(), MachineType::Int32(), |
| 182 MachineType::Int32(), MachineType::Int32()}; |
| 183 static v8::internal::MachineSignature sig(1, 7, reps); |
| 184 v8::internal::ffi::NativeFunction func = {&sig, |
| 185 reinterpret_cast<uint8_t*>(add7)}; |
| 186 |
| 187 Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func); |
| 188 |
| 189 Handle<Object> args[] = { |
| 190 isolate->factory()->NewNumber(1.0), isolate->factory()->NewNumber(2.0), |
| 191 isolate->factory()->NewNumber(3.0), isolate->factory()->NewNumber(4.0), |
| 192 isolate->factory()->NewNumber(5.0), isolate->factory()->NewNumber(6.0), |
| 193 isolate->factory()->NewNumber(7.0)}; |
| 194 Handle<Object> result = |
| 195 Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
| 196 .ToHandleChecked(); |
| 197 |
| 198 CHECK_EQ(28.0, result->Number()); |
| 199 } |
OLD | NEW |