Commit 0ecc6b06 authored by mattloring's avatar mattloring Committed by Commit bot

FFI Compiler outline based on code stub assembler. We are looking to land this...

FFI Compiler outline based on code stub assembler. We are looking to land this frame to allow specific type translation implementations to proceed in parallel.

BUG=v8:4456

Review-Url: https://codereview.chromium.org/2607993003
Cr-Commit-Position: refs/heads/master@{#42475}
parent 970d9076
......@@ -1379,6 +1379,8 @@ v8_source_set("v8_base") {
"src/fast-accessor-assembler.h",
"src/fast-dtoa.cc",
"src/fast-dtoa.h",
"src/ffi/ffi-compiler.cc",
"src/ffi/ffi-compiler.h",
"src/field-index-inl.h",
"src/field-index.h",
"src/field-type.cc",
......
......@@ -15,6 +15,7 @@
#include "src/extensions/ignition-statistics-extension.h"
#include "src/extensions/statistics-extension.h"
#include "src/extensions/trigger-failure-extension.h"
#include "src/ffi/ffi-compiler.h"
#include "src/heap/heap.h"
#include "src/isolate-inl.h"
#include "src/snapshot/natives.h"
......@@ -4196,6 +4197,8 @@ bool Genesis::InstallSpecialObjects(Handle<Context> native_context) {
WasmJs::Install(isolate);
}
InstallFFIMap(isolate);
// Expose the debug global object in global if a name for it is specified.
if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) {
// If loading fails we just bail out without installing the
......
......@@ -249,6 +249,13 @@ Node* CodeAssembler::Parameter(int value) {
return raw_assembler()->Parameter(value);
}
Node* CodeAssembler::GetJSContextParameter() {
CallDescriptor* desc = raw_assembler()->call_descriptor();
DCHECK(desc->IsJSFunctionCall());
return Parameter(Linkage::GetJSCallContextParamIndex(
static_cast<int>(desc->JSParameterCount())));
}
void CodeAssembler::Return(Node* value) {
return raw_assembler()->Return(value);
}
......@@ -602,6 +609,12 @@ template V8_EXPORT_PRIVATE Node* CodeAssembler::TailCallBytecodeDispatch(
const CallInterfaceDescriptor& descriptor, Node* target, Node*, Node*,
Node*, Node*);
Node* CodeAssembler::CallCFunctionN(Signature<MachineType>* signature,
int input_count, Node* const* inputs) {
CallDescriptor* desc = Linkage::GetSimplifiedCDescriptor(zone(), signature);
return raw_assembler()->CallN(desc, input_count, inputs);
}
Node* CodeAssembler::CallCFunction2(MachineType return_type,
MachineType arg0_type,
MachineType arg1_type, Node* function,
......
......@@ -227,6 +227,7 @@ class V8_EXPORT_PRIVATE CodeAssembler {
bool ToIntPtrConstant(Node* node, intptr_t& out_value);
Node* Parameter(int value);
Node* GetJSContextParameter();
void Return(Node* value);
void PopAndReturn(Node* pop, Node* value);
......@@ -364,6 +365,9 @@ class V8_EXPORT_PRIVATE CodeAssembler {
args...);
}
Node* CallCFunctionN(Signature<MachineType>* signature, int input_count,
Node* const* inputs);
// Call to a C function with two arguments.
Node* CallCFunction2(MachineType return_type, MachineType arg0_type,
MachineType arg1_type, Node* function, Node* arg0,
......
......@@ -330,6 +330,7 @@ enum ContextLookupFlags {
V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \
V(STRING_ITERATOR_MAP_INDEX, Map, string_iterator_map) \
V(SYMBOL_FUNCTION_INDEX, JSFunction, symbol_function) \
V(NATIVE_FUNCTION_MAP_INDEX, Map, native_function_map) \
V(WASM_FUNCTION_MAP_INDEX, Map, wasm_function_map) \
V(WASM_INSTANCE_CONSTRUCTOR_INDEX, JSFunction, wasm_instance_constructor) \
V(WASM_INSTANCE_SYM_INDEX, Symbol, wasm_instance_sym) \
......
......@@ -1384,6 +1384,7 @@ Handle<JSFunction> Factory::NewFunction(Handle<Map> map,
map.is_identical_to(isolate()->strict_function_without_prototype_map()) ||
// TODO(titzer): wasm_function_map() could be undefined here. ugly.
(*map == context->get(Context::WASM_FUNCTION_MAP_INDEX)) ||
(*map == context->get(Context::NATIVE_FUNCTION_MAP_INDEX)) ||
map.is_identical_to(isolate()->proxy_function_map()));
return NewFunction(map, info, context);
}
......
mattloring@google.com
ofrobots@google.com
// Copyright 2017 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 "src/ffi/ffi-compiler.h"
#include "src/api.h"
#include "src/code-factory.h"
namespace v8 {
namespace internal {
void InstallFFIMap(Isolate* isolate) {
Handle<Context> context(isolate->context());
DCHECK(!context->get(Context::NATIVE_FUNCTION_MAP_INDEX)->IsMap());
Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate);
InstanceType instance_type = prev_map->instance_type();
int internal_fields = JSObject::GetInternalFieldCount(*prev_map);
CHECK_EQ(0, internal_fields);
int pre_allocated =
prev_map->GetInObjectProperties() - prev_map->unused_property_fields();
int instance_size;
int in_object_properties;
JSFunction::CalculateInstanceSizeHelper(
instance_type, internal_fields, 0, &instance_size, &in_object_properties);
int unused_property_fields = in_object_properties - pre_allocated;
Handle<Map> map = Map::CopyInitialMap(
prev_map, instance_size, in_object_properties, unused_property_fields);
context->set_native_function_map(*map);
}
namespace ffi {
class FFIAssembler : public CodeStubAssembler {
public:
explicit FFIAssembler(CodeAssemblerState* state) : CodeStubAssembler(state) {}
Node* ToJS(Node* node, Node* context, MachineType type) {
UNREACHABLE();
// TODO(mattloring): Needs to be implemented.
return nullptr;
}
Node* FromJS(Node* node, Node* context, MachineType type) {
UNREACHABLE();
// TODO(mattloring): Needs to be implemented.
return nullptr;
}
void GenerateJSToNativeWrapper(NativeFunction* func) {
int params = static_cast<int>(func->sig->parameter_count());
int returns = static_cast<int>(func->sig->return_count());
ApiFunction api_func(func->start);
ExternalReference ref(&api_func, ExternalReference::DIRECT_API_CALL,
isolate());
Node* context_param = GetJSContextParameter();
Node** inputs = zone()->NewArray<Node*>(params + 1);
int input_count = 0;
inputs[input_count++] = ExternalConstant(ref);
for (int i = 0; i < params; i++) {
inputs[input_count++] =
FromJS(Parameter(i), context_param, func->sig->GetParam(i));
}
Node* call = CallCFunctionN(func->sig, input_count, inputs);
Node* return_val = UndefinedConstant();
if (returns == 1) {
return_val = ToJS(call, context_param, func->sig->GetReturn());
}
Return(return_val);
}
};
Handle<JSFunction> CompileJSToNativeWrapper(Isolate* isolate,
Handle<String> name,
NativeFunction func) {
int params = static_cast<int>(func.sig->parameter_count());
Zone zone(isolate->allocator(), ZONE_NAME);
CodeAssemblerState state(isolate, &zone, params,
Code::ComputeFlags(Code::FUNCTION), "js-to-native");
FFIAssembler assembler(&state);
assembler.GenerateJSToNativeWrapper(&func);
Handle<Code> code = assembler.GenerateCode(&state);
Handle<SharedFunctionInfo> shared =
isolate->factory()->NewSharedFunctionInfo(name, code, false);
shared->set_length(params);
shared->set_internal_formal_parameter_count(params);
Handle<JSFunction> function = isolate->factory()->NewFunction(
isolate->native_function_map(), name, code);
function->set_shared(*shared);
return function;
}
} // namespace ffi
} // namespace internal
} // namespace v8
// Copyright 2017 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.
#ifndef SRC_FFI_FFI_COMPILER_H_
#define SRC_FFI_FFI_COMPILER_H_
#include "src/code-stub-assembler.h"
#include "src/machine-type.h"
namespace v8 {
namespace internal {
typedef compiler::Node Node;
typedef compiler::CodeAssemblerState CodeAssemblerState;
void InstallFFIMap(Isolate* isolate);
namespace ffi {
typedef Signature<MachineType> FFISignature;
struct NativeFunction {
FFISignature* sig;
uint8_t* start;
};
Handle<JSFunction> CompileJSToNativeWrapper(Isolate* isolate,
Handle<String> name,
NativeFunction func);
} // namespace ffi
} // namespace internal
} // namespace v8
#endif // SRC_FFI_FFI_COMPILER_H_
......@@ -890,6 +890,8 @@
'fast-accessor-assembler.h',
'fast-dtoa.cc',
'fast-dtoa.h',
'ffi/ffi-compiler.cc',
'ffi/ffi-compiler.h',
'field-index.h',
'field-index-inl.h',
'field-type.cc',
......
......@@ -60,6 +60,7 @@ v8_executable("cctest") {
"compiler/test-run-wasm-machops.cc",
"compiler/value-helper.h",
"expression-type-collector-macros.h",
"ffi/test-ffi.cc",
"gay-fixed.cc",
"gay-fixed.h",
"gay-precision.cc",
......
......@@ -81,6 +81,7 @@
'cctest.cc',
'cctest.h',
'expression-type-collector-macros.h',
'ffi/test-ffi.cc',
'interpreter/interpreter-tester.cc',
'interpreter/interpreter-tester.h',
'interpreter/source-position-matcher.cc',
......
mattloring@google.com
ofrobots@google.com
// Copyright 2017 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 "src/codegen.h"
#include "src/ffi/ffi-compiler.h"
#include "test/cctest/cctest.h"
namespace v8 {
namespace internal {
namespace ffi {
static void hello_world() { printf("hello world from native code\n"); }
TEST(Run_FFI_Hello) {
Isolate* isolate = CcTest::InitIsolateOnce();
HandleScope scope(isolate);
Handle<String> name =
isolate->factory()->InternalizeUtf8String("hello_world");
Handle<Object> undefined = isolate->factory()->undefined_value();
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
FFISignature::Builder sig_builder(&zone, 0, 0);
NativeFunction func = {sig_builder.Build(),
reinterpret_cast<uint8_t*>(hello_world)};
Handle<JSFunction> jsfunc = CompileJSToNativeWrapper(isolate, name, func);
Handle<Object> result =
Execution::Call(isolate, jsfunc, undefined, 0, nullptr).ToHandleChecked();
CHECK(result->IsUndefined(isolate));
}
} // namespace ffi
} // namespace internal
} // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment