| Index: test/cctest/test-ffi.cc
|
| diff --git a/test/cctest/test-ffi.cc b/test/cctest/test-ffi.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..569ce8d8f4d8af644ca012b3ee9eb18c5a50b7c1
|
| --- /dev/null
|
| +++ b/test/cctest/test-ffi.cc
|
| @@ -0,0 +1,199 @@
|
| +// Copyright 2016 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <math.h>
|
| +#include <stdint.h>
|
| +#include <stdlib.h>
|
| +#include <string.h>
|
| +
|
| +#include "src/compiler/ffi-compiler.h"
|
| +
|
| +#include "test/cctest/cctest.h"
|
| +
|
| +using namespace v8::base;
|
| +using namespace v8::internal;
|
| +using namespace v8::internal::compiler;
|
| +
|
| +static int foo() {
|
| + printf("hello world from native code\n");
|
| + return 42;
|
| +}
|
| +
|
| +TEST(Run_FFI_Hello) {
|
| + Isolate* isolate = CcTest::InitIsolateOnce();
|
| + HandleScope scope(isolate);
|
| +
|
| + Handle<String> name = isolate->factory()->InternalizeUtf8String("foo");
|
| + Handle<Object> undefined = isolate->factory()->undefined_value();
|
| +
|
| + MachineType reps[] = {MachineType::Int32()};
|
| + static v8::internal::MachineSignature sig_foo(1, 0, reps);
|
| + v8::internal::ffi::NativeFunction func = {&sig_foo,
|
| + reinterpret_cast<uint8_t*>(foo)};
|
| +
|
| + Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func);
|
| +
|
| + Handle<Object> result =
|
| + Execution::Call(isolate, jsfunc, undefined, 0, nullptr).ToHandleChecked();
|
| +
|
| + CHECK_EQ(42.0, result->Number());
|
| +}
|
| +
|
| +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();
|
| +
|
| + MachineType reps[] = {MachineType::Int32(), MachineType::Int32(),
|
| + MachineType::Int32()};
|
| + static v8::internal::MachineSignature sig(1, 2, reps);
|
| + v8::internal::ffi::NativeFunction func = {&sig,
|
| + 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.
|
| + // TODO(ofrobots): should this throw instead?
|
| + {
|
| + 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.
|
| + // TODO(ofrobots): should this throw instead?
|
| + {
|
| + 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.
|
| + // TODO(ofrobots): should this throw instead?
|
| + {
|
| + 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.
|
| + // TODO(ofrobots): should this throw instead?
|
| + {
|
| + 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 add7(int x1, int x2, int x3, int x4, int x5, int x6, int x7) {
|
| + return x1 + x2 + x3 + x4 + x5 + x6 + x7;
|
| +}
|
| +
|
| +TEST(Run_FFI_add7) {
|
| + Isolate* isolate = CcTest::InitIsolateOnce();
|
| + HandleScope scope(isolate);
|
| +
|
| + Handle<String> name = isolate->factory()->InternalizeUtf8String("add7");
|
| + Handle<Object> undefined = isolate->factory()->undefined_value();
|
| +
|
| + MachineType reps[] = {MachineType::Int32(), MachineType::Int32(),
|
| + MachineType::Int32(), MachineType::Int32(),
|
| + MachineType::Int32(), MachineType::Int32(),
|
| + MachineType::Int32(), MachineType::Int32()};
|
| + static v8::internal::MachineSignature sig(1, 7, reps);
|
| + v8::internal::ffi::NativeFunction func = {&sig,
|
| + reinterpret_cast<uint8_t*>(add7)};
|
| +
|
| + Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func);
|
| +
|
| + Handle<Object> args[] = {
|
| + isolate->factory()->NewNumber(1.0), isolate->factory()->NewNumber(2.0),
|
| + isolate->factory()->NewNumber(3.0), isolate->factory()->NewNumber(4.0),
|
| + isolate->factory()->NewNumber(5.0), isolate->factory()->NewNumber(6.0),
|
| + isolate->factory()->NewNumber(7.0)};
|
| + Handle<Object> result =
|
| + Execution::Call(isolate, jsfunc, undefined, arraysize(args), args)
|
| + .ToHandleChecked();
|
| +
|
| + CHECK_EQ(28.0, result->Number());
|
| +}
|
|
|