Index: test/cctest/ffi/test-ffi.cc |
diff --git a/test/cctest/ffi/test-ffi.cc b/test/cctest/ffi/test-ffi.cc |
index 8a82a21dec6e628199cad10a248f02d8983417a9..96eb8410432d945352557c03eaadb3a1095b96d6 100644 |
--- a/test/cctest/ffi/test-ffi.cc |
+++ b/test/cctest/ffi/test-ffi.cc |
@@ -34,6 +34,187 @@ TEST(Run_FFI_Hello) { |
CHECK(result->IsUndefined(isolate)); |
} |
+static int add2(int x, int y) { return x + y; } |
+ |
+TEST(Run_FFI_add2) { |
+ Isolate* isolate = CcTest::InitIsolateOnce(); |
+ HandleScope scope(isolate); |
+ |
+ Handle<String> name = isolate->factory()->InternalizeUtf8String("add2"); |
+ Handle<Object> undefined = isolate->factory()->undefined_value(); |
+ |
+ AccountingAllocator allocator; |
+ Zone zone(&allocator, ZONE_NAME); |
+ FFISignature::Builder sig_builder(&zone, 1, 2); |
+ sig_builder.AddReturn(FFIType::kInt32); |
+ sig_builder.AddParam(FFIType::kInt32); |
+ sig_builder.AddParam(FFIType::kInt32); |
+ NativeFunction func = {sig_builder.Build(), reinterpret_cast<uint8_t*>(add2)}; |
+ |
+ Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func); |
+ |
+ // Simple math should work. |
+ { |
+ Handle<Object> args[] = {isolate->factory()->NewNumber(1.0), |
+ isolate->factory()->NewNumber(41.0)}; |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(42.0, result->Number()); |
+ } |
+ |
+ // Truncate floating point to integer. |
+ { |
+ Handle<Object> args[] = {isolate->factory()->NewNumber(1.9), |
+ isolate->factory()->NewNumber(41.0)}; |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(42.0, result->Number()); |
+ } |
+ |
+ // INT_MAX + 1 should wrap. |
+ { |
+ Handle<Object> args[] = {isolate->factory()->NewNumber(kMaxInt), |
+ isolate->factory()->NewNumber(1)}; |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(kMinInt, result->Number()); |
+ } |
+ |
+ // INT_MIN + -1 should wrap. |
+ { |
+ Handle<Object> args[] = {isolate->factory()->NewNumber(kMinInt), |
+ isolate->factory()->NewNumber(-1)}; |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(kMaxInt, result->Number()); |
+ } |
+ |
+ // Numbers get truncated to the 32 least significant bits. |
+ { |
+ Handle<Object> args[] = {isolate->factory()->NewNumber(1ull << 40), |
+ isolate->factory()->NewNumber(-1)}; |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(-1, result->Number()); |
+ } |
+ |
+ // String '57' converts to 57. |
+ { |
+ Handle<Object> args[] = { |
+ isolate->factory()->NewStringFromAsciiChecked("57"), |
+ isolate->factory()->NewNumber(41.0)}; |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(98.0, result->Number()); |
+ } |
+ |
+ // String 'foo' converts to 0. |
+ { |
+ Handle<Object> args[] = { |
+ isolate->factory()->NewStringFromAsciiChecked("foo"), |
+ isolate->factory()->NewNumber(41.0)}; |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(41.0, result->Number()); |
+ } |
+ |
+ // String '58o' converts to 0. |
+ { |
+ Handle<Object> args[] = { |
+ isolate->factory()->NewStringFromAsciiChecked("58o"), |
+ isolate->factory()->NewNumber(41.0)}; |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(41.0, result->Number()); |
+ } |
+ |
+ // NaN converts to 0. |
+ { |
+ Handle<Object> args[] = {isolate->factory()->nan_value(), |
+ isolate->factory()->NewNumber(41.0)}; |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(41.0, result->Number()); |
+ } |
+ |
+ // null converts to 0. |
+ { |
+ Handle<Object> args[] = {isolate->factory()->null_value(), |
+ isolate->factory()->NewNumber(41.0)}; |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(41.0, result->Number()); |
+ } |
+} |
+ |
+static int add6(int a, int b, int c, int d, int e, int f) { |
+ return a + b + c + d + e + f; |
+} |
+ |
+TEST(Run_FFI_add6) { |
+ Isolate* isolate = CcTest::InitIsolateOnce(); |
+ HandleScope scope(isolate); |
+ |
+ Handle<String> name = isolate->factory()->InternalizeUtf8String("add6"); |
+ Handle<Object> undefined = isolate->factory()->undefined_value(); |
+ |
+ AccountingAllocator allocator; |
+ Zone zone(&allocator, ZONE_NAME); |
+ FFISignature::Builder sig_builder(&zone, 1, 7); |
+ sig_builder.AddReturn(FFIType::kInt32); |
+ for (int i = 0; i < 7; i++) { |
+ sig_builder.AddParam(FFIType::kInt32); |
+ } |
+ NativeFunction func = {sig_builder.Build(), reinterpret_cast<uint8_t*>(add6)}; |
+ |
+ Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func); |
+ Handle<Object> args[] = { |
+ isolate->factory()->NewNumber(1), isolate->factory()->NewNumber(2), |
+ isolate->factory()->NewNumber(3), isolate->factory()->NewNumber(4), |
+ isolate->factory()->NewNumber(5), isolate->factory()->NewNumber(6)}; |
+ |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ |
+ CHECK_EQ(21.0, result->Number()); |
+ |
+ { |
+ // Ensure builtin frames are generated |
+ FLAG_allow_natives_syntax = true; |
+ v8::Local<v8::Value> res = CompileRun( |
+ "var o = { valueOf: function() { %DebugTrace(); return 1; } }; o;"); |
+ Handle<JSReceiver> param(v8::Utils::OpenHandle(v8::Object::Cast(*res))); |
+ Handle<Object> args[] = {param, |
+ isolate->factory()->NewNumber(2), |
+ isolate->factory()->NewNumber(3), |
+ isolate->factory()->NewNumber(4), |
+ isolate->factory()->NewNumber(5), |
+ isolate->factory()->NewNumber(6), |
+ isolate->factory()->NewNumber(21)}; |
+ |
+ Handle<Object> result = |
+ Execution::Call(isolate, jsfunc, undefined, arraysize(args), args) |
+ .ToHandleChecked(); |
+ CHECK_EQ(21.0, result->Number()); |
+ CHECK_EQ( |
+ 1.0, |
+ res->NumberValue( |
+ reinterpret_cast<v8::Isolate*>(isolate)->GetCurrentContext()) |
+ .ToChecked()); |
+ } |
+} |
+ |
} // namespace ffi |
} // namespace internal |
} // namespace v8 |