Line data Source code
1 : // Copyright 2017 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 "src/ffi/ffi-compiler.h"
6 : #include "src/api.h"
7 : #include "src/code-factory.h"
8 : #include "src/objects-inl.h"
9 :
10 : namespace v8 {
11 : namespace internal {
12 :
13 105382 : void InstallFFIMap(Isolate* isolate) {
14 : Handle<Context> context(isolate->context());
15 : DCHECK(!context->get(Context::NATIVE_FUNCTION_MAP_INDEX)->IsMap());
16 : Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate);
17 :
18 : InstanceType instance_type = prev_map->instance_type();
19 105383 : int embedder_fields = JSObject::GetEmbedderFieldCount(*prev_map);
20 105382 : CHECK_EQ(0, embedder_fields);
21 : int pre_allocated =
22 105382 : prev_map->GetInObjectProperties() - prev_map->unused_property_fields();
23 : int instance_size;
24 : int in_object_properties;
25 : JSFunction::CalculateInstanceSizeHelper(
26 105382 : instance_type, embedder_fields, 0, &instance_size, &in_object_properties);
27 105382 : int unused_property_fields = in_object_properties - pre_allocated;
28 : Handle<Map> map = Map::CopyInitialMap(
29 105382 : prev_map, instance_size, in_object_properties, unused_property_fields);
30 : context->set_native_function_map(*map);
31 105383 : }
32 :
33 : namespace ffi {
34 :
35 : class FFIAssembler : public CodeStubAssembler {
36 : public:
37 21 : explicit FFIAssembler(CodeAssemblerState* state) : CodeStubAssembler(state) {}
38 :
39 14 : Node* ToJS(Node* node, Node* context, FFIType type) {
40 14 : switch (type) {
41 : case FFIType::kInt32:
42 14 : return ChangeInt32ToTagged(node);
43 : }
44 0 : UNREACHABLE();
45 : return nullptr;
46 : }
47 :
48 63 : Node* FromJS(Node* node, Node* context, FFIType type) {
49 63 : switch (type) {
50 : case FFIType::kInt32:
51 63 : return TruncateTaggedToWord32(context, node);
52 : }
53 0 : UNREACHABLE();
54 : return nullptr;
55 : }
56 :
57 77 : MachineType FFIToMachineType(FFIType type) {
58 77 : switch (type) {
59 : case FFIType::kInt32:
60 : return MachineType::Int32();
61 : }
62 0 : UNREACHABLE();
63 : return MachineType::None();
64 : }
65 :
66 217 : Signature<MachineType>* FFIToMachineSignature(FFISignature* sig) {
67 : Signature<MachineType>::Builder sig_builder(zone(), sig->return_count(),
68 21 : sig->parameter_count());
69 70 : for (size_t i = 0; i < sig->return_count(); i++) {
70 14 : sig_builder.AddReturn(FFIToMachineType(sig->GetReturn(i)));
71 : }
72 147 : for (size_t j = 0; j < sig->parameter_count(); j++) {
73 63 : sig_builder.AddParam(FFIToMachineType(sig->GetParam(j)));
74 : }
75 21 : return sig_builder.Build();
76 : }
77 :
78 21 : void GenerateJSToNativeWrapper(NativeFunction* func) {
79 98 : int params = static_cast<int>(func->sig->parameter_count());
80 21 : int returns = static_cast<int>(func->sig->return_count());
81 21 : ApiFunction api_func(func->start);
82 : ExternalReference ref(&api_func, ExternalReference::BUILTIN_CALL,
83 21 : isolate());
84 :
85 21 : Node* context_param = GetJSContextParameter();
86 :
87 21 : Node** inputs = zone()->NewArray<Node*>(params + 1);
88 : int input_count = 0;
89 21 : inputs[input_count++] = ExternalConstant(ref);
90 84 : for (int i = 0; i < params; i++) {
91 63 : inputs[input_count++] =
92 126 : FromJS(Parameter(i), context_param, func->sig->GetParam(i));
93 : }
94 :
95 : Node* call =
96 21 : CallCFunctionN(FFIToMachineSignature(func->sig), input_count, inputs);
97 21 : Node* return_val = UndefinedConstant();
98 21 : if (returns == 1) {
99 28 : return_val = ToJS(call, context_param, func->sig->GetReturn());
100 : }
101 21 : Return(return_val);
102 21 : }
103 : };
104 :
105 42 : Handle<JSFunction> CompileJSToNativeWrapper(Isolate* isolate,
106 : Handle<String> name,
107 : NativeFunction func) {
108 21 : int params = static_cast<int>(func.sig->parameter_count());
109 21 : Zone zone(isolate->allocator(), ZONE_NAME);
110 : CodeAssemblerState state(isolate, &zone, params,
111 42 : Code::ComputeFlags(Code::BUILTIN), "js-to-native");
112 : FFIAssembler assembler(&state);
113 21 : assembler.GenerateJSToNativeWrapper(&func);
114 21 : Handle<Code> code = assembler.GenerateCode(&state);
115 :
116 : Handle<SharedFunctionInfo> shared =
117 21 : isolate->factory()->NewSharedFunctionInfo(name, code, false);
118 : shared->set_length(params);
119 : shared->set_internal_formal_parameter_count(params);
120 : Handle<JSFunction> function = isolate->factory()->NewFunction(
121 21 : isolate->native_function_map(), name, code);
122 21 : function->set_shared(*shared);
123 42 : return function;
124 : }
125 :
126 : } // namespace ffi
127 : } // namespace internal
128 : } // namespace v8
|