Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: src/runtime/runtime-ffi.cc

Issue 2250863002: WIP: prototype ffi support (from 2084663004) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/runtime/runtime.h ('k') | src/snapshot/code-serializer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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/runtime/runtime-utils.h"
6
7 #include "src/arguments.h"
8 #include "src/assembler.h"
9 #include "src/code-factory.h"
10 #include "src/compilation-info.h"
11 #include "src/compiler/common-operator.h"
12 #include "src/compiler/ffi-compiler.h"
13 #include "src/compiler/graph.h"
14 #include "src/compiler/js-graph.h"
15 #include "src/compiler/linkage.h"
16 #include "src/compiler/machine-operator.h"
17 #include "src/compiler/pipeline.h"
18
19 namespace v8 {
20 namespace internal {
21
22 using namespace v8::internal::compiler;
23
24 #define WORD_SIZE 8
25
26 // TODO(mattloring): need pool per function, not global
27 List<char *> mem_pool(10);
28 std::map<int, void *> callback_compilations;
29
30 static int StructSize(ffi::FFIStructSignature *sig) {
31 int total_size = 0;
32 int curr_alignment = 0;
33 for (size_t i = 0; i < sig->elem_count; i++) {
34 int elem_size = TypeSize(sig->elems[i].type->type);
35 // Account for padding
36 if (elem_size + curr_alignment > WORD_SIZE) {
37 total_size += WORD_SIZE - curr_alignment;
38 curr_alignment = 0;
39 }
40 curr_alignment += elem_size;
41 total_size += elem_size;
42 }
43 return total_size;
44 }
45
46 RUNTIME_FUNCTION(Runtime_JSStringToCharPtr) {
47 HandleScope scope(isolate);
48 DCHECK_EQ(1, args.length());
49 Handle<String> string;
50 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
51 isolate, string, Object::ToString(isolate, args.at<Object>(0)));
52 int length = string->length() + 1;
53 char *str = reinterpret_cast<char *>(malloc(length));
54 snprintf(str, length, "%s", ((*string)->ToCString()).release());
55 mem_pool.Add(str);
56 // TODO(mattloring): should this be a foreign somehow? this cast is not
57 // correct
58 return reinterpret_cast<Object *>(str);
59 }
60
61 RUNTIME_FUNCTION(Runtime_TypedArrayToUint8Ptr) {
62 HandleScope scope(isolate);
63 DCHECK_EQ(1, args.length());
64 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, input_obj, 0);
65 Handle<JSTypedArray> array(JSTypedArray::cast(*input_obj));
66 uint8_t *contents =
67 reinterpret_cast<uint8_t *>(array->GetBuffer()->backing_store());
68 size_t offset = NumberToSize(array->byte_offset());
69 size_t length = NumberToSize(array->byte_length());
70 char *result = reinterpret_cast<char *>(malloc(length));
71 memcpy(result, contents + offset, length);
72 mem_pool.Add(result);
73 // TODO(mattloring): should this be a foreign somehow? this cast is not
74 // correct
75 return reinterpret_cast<Object *>(result);
76 }
77
78 RUNTIME_FUNCTION(Runtime_BufferToPtrNoCopy) {
79 HandleScope scope(isolate);
80 DCHECK_EQ(1, args.length());
81 CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, input_obj, 0);
82 Handle<JSTypedArray> array(JSTypedArray::cast(*input_obj));
83 uint8_t *contents =
84 reinterpret_cast<uint8_t *>(array->GetBuffer()->backing_store());
85 size_t offset = NumberToSize(array->byte_offset());
86 // TODO(mattloring): should this be a foreign somehow? this cast is not
87 // correct
88 return reinterpret_cast<Object *>(contents + offset);
89 }
90
91 RUNTIME_FUNCTION(Runtime_CharPtrToJSString) {
92 HandleScope scope(isolate);
93 DCHECK_EQ(1, args.length());
94 char *str = reinterpret_cast<char *>(args[0]);
95 Handle<String> name = isolate->factory()->InternalizeUtf8String(str);
96 free(str);
97 return *name;
98 }
99
100 static void CallNoReturn(Isolate *isolate, Object *callable, Object *receiver,
101 int argc, Object *argv[]) {
102 HandleScope scope(isolate);
103 Handle<Object> call_handle(callable, isolate);
104 Handle<Object> rec_handle(receiver, isolate);
105 Handle<Object> *argv_handles = new Handle<Object>[ argc ];
106 for (int i = 0; i < argc; i++) {
107 Handle<Object> arg_handle(argv[i], isolate);
108 argv_handles[i] = arg_handle;
109 }
110 // TODO(mattloring): retrieve return value instead of USE
111 USE(i::Execution::Call(isolate, call_handle, rec_handle, argc, argv_handles));
112 }
113
114 RUNTIME_FUNCTION(Runtime_JSFunctionToFnPtr) {
115 HandleScope scope(isolate);
116 DCHECK_EQ(2, args.length());
117 CONVERT_ARG_HANDLE_CHECKED(JSFunction, input_obj, 0);
118 Handle<JSFunction> func(JSFunction::cast(*input_obj));
119
120 if (callback_compilations[func->shared()->start_position()]) {
121 // Use cached result
122 // TODO(mattloring): cache on better property than start position
123 return reinterpret_cast<Object *>(
124 callback_compilations[func->shared()->start_position()]);
125 }
126
127 ffi::FFISignature *sig = reinterpret_cast<ffi::FFISignature *>(args[1]);
128 Zone zone(isolate->allocator(), ZONE_NAME);
129 Graph graph(&zone);
130 CommonOperatorBuilder common(&zone);
131 MachineOperatorBuilder machine(&zone);
132 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
133
134 int param_count = static_cast<int>(sig->parameter_count());
135
136 MachineType invoke_reps[] = {MachineType::Pointer(), MachineType::Pointer(),
137 MachineType::Pointer(), MachineType::Int64(),
138 MachineType::Pointer()};
139 MachineSignature invoke_sig(0, 5, invoke_reps);
140 CallDescriptor *invoke_desc =
141 Linkage::GetSimplifiedCDescriptor(&zone, &invoke_sig);
142
143 // Unmarshall arguments coming from C going to JS
144 // Marshall value returned from JS back to C
145 Node *start =
146 graph.NewNode(common.Start(3 + param_count)); // 4 + param count
147
148 FFIGraphBuilder builder(&zone, &jsgraph);
149 builder.set_control_ptr(&start);
150 builder.set_effect_ptr(&start);
151
152 graph.SetStart(start);
153
154 Node *context = jsgraph.HeapConstant(Handle<Context>(func->context()));
155 Object **call_args = new Object *[param_count];
156 Node *call_args_node = graph.NewNode(common.ExternalConstant(
157 ExternalReference(reinterpret_cast<Address>(call_args), isolate)));
158 Node *prev_arg_translation = start;
159 if (param_count > 0) {
160 for (int i = 0; i < param_count; i++) { // Arguments
161 Node *translated_param = builder.ToJS(
162 graph.NewNode(common.Parameter(i), start), context, sig->GetParam(i));
163 prev_arg_translation = graph.NewNode(
164 machine.Store(StoreRepresentation(
165 MachineRepresentation::kTaggedPointer, kNoWriteBarrier)),
166 call_args_node, jsgraph.Int32Constant(i), translated_param,
167 prev_arg_translation, start);
168 }
169 }
170
171 int index = 0;
172 Node **arguments = zone.NewArray<Node *>(8);
173 arguments[index++] = graph.NewNode(
174 common.Int64Constant(reinterpret_cast<int64_t>(&CallNoReturn)));
175 arguments[index++] = graph.NewNode(common.ExternalConstant(
176 ExternalReference(reinterpret_cast<Address>(isolate), isolate)));
177 arguments[index++] = jsgraph.HeapConstant(func);
178 arguments[index++] = jsgraph.UndefinedConstant();
179 arguments[index++] = jsgraph.Int64Constant(param_count);
180 arguments[index++] = call_args_node;
181 arguments[index++] = prev_arg_translation;
182 arguments[index++] = start;
183 Node *call = graph.NewNode(common.Call(invoke_desc), index, arguments);
184 Node *call_control = graph.NewNode(common.IfSuccess(), call);
185 // TODO(mattloring): retval = call;
186 Node *retval = jsgraph.Constant(42);
187 if (sig->return_count() != 0) {
188 retval = builder.FromJS(retval, context, sig->GetReturn());
189 }
190 Node *ret = graph.NewNode(common.Return(), jsgraph.Int32Constant(0), retval,
191 call, call_control);
192 graph.SetEnd(graph.NewNode(common.End(1), ret));
193
194 MachineType *reps = builder.GetMachineTypes(sig);
195 MachineSignature mach_sig(sig->return_count(), param_count, reps);
196
197 CallDescriptor *desc = Linkage::GetSimplifiedCDescriptor(&zone, &mach_sig);
198
199 Code::Flags flags = Code::ComputeFlags(Code::STUB);
200
201 CompilationInfo info(ArrayVector("js-to-native-cb"), jsgraph.isolate(), &zone,
202 flags);
203 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, desc, &graph);
204 callback_compilations[func->shared()->start_position()] = code->entry();
205 // TODO(mattloring): should this be a foreign somehow? this cast is not
206 // correct
207 return reinterpret_cast<Object *>(code->entry());
208 }
209
210 RUNTIME_FUNCTION(Runtime_JSObjectToStructPtr) {
211 HandleScope scope(isolate);
212 DCHECK_EQ(2, args.length());
213 Handle<JSObject> obj(JSObject::cast(args[0]));
214 ffi::FFIStructSignature *sig =
215 reinterpret_cast<ffi::FFIStructSignature *>(args[1]);
216 char *result = reinterpret_cast<char *>(malloc(StructSize(sig)));
217 char *write_pos = result;
218 int alignment = 0;
219 for (size_t i = 0; i < sig->elem_count; i++) {
220 v8::ffi::FFIStructElement elem = sig->elems[i];
221 int elem_size = TypeSize(elem.type->type);
222 Handle<String> name = isolate->factory()->InternalizeUtf8String(elem.name);
223 LookupIterator it(obj, name);
224 Handle<Object> value = Object::GetProperty(&it).ToHandleChecked();
225 if (elem_size + alignment > WORD_SIZE) {
226 memset(write_pos, 0, WORD_SIZE - alignment);
227 write_pos += (WORD_SIZE - alignment);
228 alignment = 0;
229 }
230 WriteObject(value, elem.type->type, write_pos);
231 write_pos += elem_size;
232 alignment += elem_size;
233 }
234 mem_pool.Add(result);
235 // TODO(mattloring): should this be a foreign somehow? this cast is not
236 // correct
237 return reinterpret_cast<Object *>(result);
238 }
239
240 RUNTIME_FUNCTION(Runtime_PointerToForeign) {
241 HandleScope scope(isolate);
242 DCHECK_EQ(1, args.length());
243 intptr_t *ptr = reinterpret_cast<intptr_t *>(args[0]);
244 Handle<Foreign> foreign =
245 isolate->factory()->NewForeign(reinterpret_cast<Address>(ptr));
246 return *foreign;
247 }
248
249 RUNTIME_FUNCTION(Runtime_ForeignToPointer) {
250 HandleScope scope(isolate);
251 DCHECK_EQ(1, args.length());
252 Handle<Foreign> foreign(Foreign::cast(args[0]));
253 // TODO(mattloring): should this be a foreign somehow? this cast is not
254 // correct
255 return reinterpret_cast<Object *>(foreign->foreign_address());
256 }
257
258 RUNTIME_FUNCTION(Runtime_ReleaseFFIMemPool) {
259 HandleScope scope(isolate);
260 for (char *addr : mem_pool) {
261 free(addr);
262 }
263 mem_pool.Clear();
264 return isolate->heap()->ToBoolean(true);
265 }
266 } // namespace internal
267 } // namespace v8
OLDNEW
« no previous file with comments | « src/runtime/runtime.h ('k') | src/snapshot/code-serializer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698