| 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
|
|
|