• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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/d8/d8.h"
6 
7 #include "include/v8-fast-api-calls.h"
8 #include "include/v8-template.h"
9 #include "src/api/api-inl.h"
10 
11 // This file exposes a d8.test.fast_c_api object, which adds testing facility
12 // for writing mjsunit tests that exercise fast API calls. The fast_c_api object
13 // contains an `add_all` method with the following signature:
14 // double add_all(bool /*should_fallback*/, int32_t, uint32_t,
15 //   int64_t, uint64_t, float, double), that is wired as a "fast API" method.
16 // The fast_c_api object also supports querying the number of fast/slow calls
17 // and resetting these counters.
18 
19 // Make sure to sync the following with src/compiler/globals.h.
20 #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64)
21 #define V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
22 #endif
23 
24 namespace v8 {
25 namespace {
26 
27 #define CHECK_SELF_OR_FALLBACK(return_value) \
28   if (!self) {                               \
29     options.fallback = 1;                    \
30     return return_value;                     \
31   }
32 
33 #define CHECK_SELF_OR_THROW()                                               \
34   if (!self) {                                                              \
35     args.GetIsolate()->ThrowError(                                          \
36         "This method is not defined on objects inheriting from FastCAPI."); \
37     return;                                                                 \
38   }
39 
40 class FastCApiObject {
41  public:
42   static FastCApiObject& instance();
43 
44 #ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
AddAllFastCallbackPatch(AnyCType receiver,AnyCType should_fallback,AnyCType arg_i32,AnyCType arg_u32,AnyCType arg_i64,AnyCType arg_u64,AnyCType arg_f32,AnyCType arg_f64,AnyCType options)45   static AnyCType AddAllFastCallbackPatch(AnyCType receiver,
46                                           AnyCType should_fallback,
47                                           AnyCType arg_i32, AnyCType arg_u32,
48                                           AnyCType arg_i64, AnyCType arg_u64,
49                                           AnyCType arg_f32, AnyCType arg_f64,
50                                           AnyCType options) {
51     AnyCType ret;
52     ret.double_value = AddAllFastCallback(
53         receiver.object_value, should_fallback.bool_value, arg_i32.int32_value,
54         arg_u32.uint32_value, arg_i64.int64_value, arg_u64.uint64_value,
55         arg_f32.float_value, arg_f64.double_value, *options.options_value);
56     return ret;
57   }
58 
59 #endif  //  V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
AddAllFastCallback(Local<Object> receiver,bool should_fallback,int32_t arg_i32,uint32_t arg_u32,int64_t arg_i64,uint64_t arg_u64,float arg_f32,double arg_f64,FastApiCallbackOptions & options)60   static double AddAllFastCallback(Local<Object> receiver, bool should_fallback,
61                                    int32_t arg_i32, uint32_t arg_u32,
62                                    int64_t arg_i64, uint64_t arg_u64,
63                                    float arg_f32, double arg_f64,
64                                    FastApiCallbackOptions& options) {
65     FastCApiObject* self = UnwrapObject(receiver);
66     CHECK_SELF_OR_FALLBACK(0);
67     self->fast_call_count_++;
68 
69     if (should_fallback) {
70       options.fallback = true;
71       return 0;
72     } else {
73       options.fallback = false;
74     }
75 
76     return static_cast<double>(arg_i32) + static_cast<double>(arg_u32) +
77            static_cast<double>(arg_i64) + static_cast<double>(arg_u64) +
78            static_cast<double>(arg_f32) + arg_f64;
79   }
80 
81 #ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
AddAllFastCallbackNoOptionsPatch(AnyCType receiver,AnyCType should_fallback,AnyCType arg_i32,AnyCType arg_u32,AnyCType arg_i64,AnyCType arg_u64,AnyCType arg_f32,AnyCType arg_f64)82   static AnyCType AddAllFastCallbackNoOptionsPatch(
83       AnyCType receiver, AnyCType should_fallback, AnyCType arg_i32,
84       AnyCType arg_u32, AnyCType arg_i64, AnyCType arg_u64, AnyCType arg_f32,
85       AnyCType arg_f64) {
86     AnyCType ret;
87     ret.double_value = AddAllFastCallbackNoOptions(
88         receiver.object_value, should_fallback.bool_value, arg_i32.int32_value,
89         arg_u32.uint32_value, arg_i64.int64_value, arg_u64.uint64_value,
90         arg_f32.float_value, arg_f64.double_value);
91     return ret;
92   }
93 #endif  //  V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
AddAllFastCallbackNoOptions(Local<Object> receiver,bool should_fallback,int32_t arg_i32,uint32_t arg_u32,int64_t arg_i64,uint64_t arg_u64,float arg_f32,double arg_f64)94   static double AddAllFastCallbackNoOptions(Local<Object> receiver,
95                                             bool should_fallback,
96                                             int32_t arg_i32, uint32_t arg_u32,
97                                             int64_t arg_i64, uint64_t arg_u64,
98                                             float arg_f32, double arg_f64) {
99     FastCApiObject* self;
100 
101     // For Wasm call, we don't pass FastCApiObject as the receiver, so we need
102     // to retrieve the FastCApiObject instance from a static variable.
103     if (Utils::OpenHandle(*receiver)->IsJSGlobalProxy() ||
104         Utils::OpenHandle(*receiver)->IsUndefined()) {
105       // Note: FastCApiObject::instance() returns the reference of an object
106       // allocated in thread-local storage, its value cannot be stored in a
107       // static variable here.
108       self = &FastCApiObject::instance();
109     } else {
110       // Fuzzing code can call this function from JS; in this case the receiver
111       // should be a FastCApiObject.
112       self = UnwrapObject(receiver);
113       CHECK_NOT_NULL(self);
114     }
115     self->fast_call_count_++;
116 
117     return static_cast<double>(arg_i32) + static_cast<double>(arg_u32) +
118            static_cast<double>(arg_i64) + static_cast<double>(arg_u64) +
119            static_cast<double>(arg_f32) + arg_f64;
120   }
121 
AddAllSlowCallback(const FunctionCallbackInfo<Value> & args)122   static void AddAllSlowCallback(const FunctionCallbackInfo<Value>& args) {
123     Isolate* isolate = args.GetIsolate();
124 
125     FastCApiObject* self = UnwrapObject(args.This());
126     CHECK_SELF_OR_THROW();
127     self->slow_call_count_++;
128 
129     HandleScope handle_scope(isolate);
130 
131     double sum = 0;
132     if (args.Length() > 1 && args[1]->IsNumber()) {
133       sum += args[1]->Int32Value(isolate->GetCurrentContext()).FromJust();
134     }
135     if (args.Length() > 2 && args[2]->IsNumber()) {
136       sum += args[2]->Uint32Value(isolate->GetCurrentContext()).FromJust();
137     }
138     if (args.Length() > 3 && args[3]->IsNumber()) {
139       sum += args[3]->IntegerValue(isolate->GetCurrentContext()).FromJust();
140     }
141     if (args.Length() > 4 && args[4]->IsNumber()) {
142       sum += args[4]->IntegerValue(isolate->GetCurrentContext()).FromJust();
143     }
144     if (args.Length() > 5 && args[5]->IsNumber()) {
145       sum += args[5]->NumberValue(isolate->GetCurrentContext()).FromJust();
146     } else {
147       sum += std::numeric_limits<double>::quiet_NaN();
148     }
149     if (args.Length() > 6 && args[6]->IsNumber()) {
150       sum += args[6]->NumberValue(isolate->GetCurrentContext()).FromJust();
151     } else {
152       sum += std::numeric_limits<double>::quiet_NaN();
153     }
154 
155     args.GetReturnValue().Set(Number::New(isolate, sum));
156   }
157 
158 #ifdef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
159   typedef double Type;
160 #else
161   typedef int32_t Type;
162 #endif  // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
163 #ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
AddAllSequenceFastCallbackPatch(AnyCType receiver,AnyCType should_fallback,AnyCType seq_arg,AnyCType options)164   static AnyCType AddAllSequenceFastCallbackPatch(AnyCType receiver,
165                                                   AnyCType should_fallback,
166                                                   AnyCType seq_arg,
167                                                   AnyCType options) {
168     AnyCType ret;
169 #ifdef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
170     ret.double_value = AddAllSequenceFastCallback(
171         receiver.object_value, should_fallback.bool_value,
172         seq_arg.sequence_value, *options.options_value);
173 #else
174     ret.int32_value = AddAllSequenceFastCallback(
175         receiver.object_value, should_fallback.bool_value,
176         seq_arg.sequence_value, *options.options_value);
177 #endif  // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
178     return ret;
179   }
180 #endif  //  V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
AddAllSequenceFastCallback(Local<Object> receiver,bool should_fallback,Local<Array> seq_arg,FastApiCallbackOptions & options)181   static Type AddAllSequenceFastCallback(Local<Object> receiver,
182                                          bool should_fallback,
183                                          Local<Array> seq_arg,
184                                          FastApiCallbackOptions& options) {
185     FastCApiObject* self = UnwrapObject(receiver);
186     CHECK_SELF_OR_FALLBACK(0);
187     self->fast_call_count_++;
188 
189     if (should_fallback) {
190       options.fallback = true;
191       return 0;
192     }
193 
194     uint32_t length = seq_arg->Length();
195     if (length > 1024) {
196       options.fallback = true;
197       return 0;
198     }
199 
200     Type buffer[1024];
201     bool result = TryToCopyAndConvertArrayToCppBuffer<
202         CTypeInfoBuilder<Type>::Build().GetId(), Type>(seq_arg, buffer, 1024);
203     if (!result) {
204       options.fallback = true;
205       return 0;
206     }
207     DCHECK_EQ(seq_arg->Length(), length);
208 
209     Type sum = 0;
210     for (uint32_t i = 0; i < length; ++i) {
211       sum += buffer[i];
212     }
213 
214     return sum;
215   }
AddAllSequenceSlowCallback(const FunctionCallbackInfo<Value> & args)216   static void AddAllSequenceSlowCallback(
217       const FunctionCallbackInfo<Value>& args) {
218     Isolate* isolate = args.GetIsolate();
219 
220     FastCApiObject* self = UnwrapObject(args.This());
221     CHECK_SELF_OR_THROW();
222 
223     HandleScope handle_scope(isolate);
224 
225     if (args.Length() < 2) {
226       self->slow_call_count_++;
227       isolate->ThrowError("This method expects at least 2 arguments.");
228       return;
229     }
230     if (args[1]->IsTypedArray()) {
231       AddAllTypedArraySlowCallback(args);
232       return;
233     }
234     self->slow_call_count_++;
235     if (args[1]->IsUndefined()) {
236       Type dummy_result = 0;
237       args.GetReturnValue().Set(Number::New(isolate, dummy_result));
238       return;
239     }
240     if (!args[1]->IsArray()) {
241       isolate->ThrowError("This method expects an array as a second argument.");
242       return;
243     }
244 
245     Local<Array> seq_arg = args[1].As<Array>();
246     uint32_t length = seq_arg->Length();
247     if (length > 1024) {
248       isolate->ThrowError(
249           "Invalid length of array, must be between 0 and 1024.");
250       return;
251     }
252 
253     Type sum = 0;
254     for (uint32_t i = 0; i < length; ++i) {
255       v8::Local<v8::Value> element =
256           seq_arg
257               ->Get(isolate->GetCurrentContext(),
258                     v8::Integer::NewFromUnsigned(isolate, i))
259               .ToLocalChecked();
260       if (element->IsNumber()) {
261         double value = element->ToNumber(isolate->GetCurrentContext())
262                            .ToLocalChecked()
263                            ->Value();
264         sum += value;
265       } else if (element->IsUndefined()) {
266         // Hole: ignore the element.
267       } else {
268         isolate->ThrowError("unexpected element type in JSArray");
269         return;
270       }
271     }
272     args.GetReturnValue().Set(Number::New(isolate, sum));
273   }
274 #ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
275   template <typename T>
276   static const FastApiTypedArray<T>* AnyCTypeToTypedArray(AnyCType arg);
277 
278   template <>
AnyCTypeToTypedArray(AnyCType arg)279   const FastApiTypedArray<int32_t>* AnyCTypeToTypedArray<int32_t>(
280       AnyCType arg) {
281     return arg.int32_ta_value;
282   }
283   template <>
AnyCTypeToTypedArray(AnyCType arg)284   const FastApiTypedArray<uint32_t>* AnyCTypeToTypedArray<uint32_t>(
285       AnyCType arg) {
286     return arg.uint32_ta_value;
287   }
288   template <>
AnyCTypeToTypedArray(AnyCType arg)289   const FastApiTypedArray<int64_t>* AnyCTypeToTypedArray<int64_t>(
290       AnyCType arg) {
291     return arg.int64_ta_value;
292   }
293   template <>
AnyCTypeToTypedArray(AnyCType arg)294   const FastApiTypedArray<uint64_t>* AnyCTypeToTypedArray<uint64_t>(
295       AnyCType arg) {
296     return arg.uint64_ta_value;
297   }
298   template <>
AnyCTypeToTypedArray(AnyCType arg)299   const FastApiTypedArray<float>* AnyCTypeToTypedArray<float>(AnyCType arg) {
300     return arg.float_ta_value;
301   }
302   template <>
AnyCTypeToTypedArray(AnyCType arg)303   const FastApiTypedArray<double>* AnyCTypeToTypedArray<double>(AnyCType arg) {
304     return arg.double_ta_value;
305   }
306 
307   template <typename T>
AddAllTypedArrayFastCallbackPatch(AnyCType receiver,AnyCType should_fallback,AnyCType typed_array_arg,AnyCType options)308   static AnyCType AddAllTypedArrayFastCallbackPatch(AnyCType receiver,
309                                                     AnyCType should_fallback,
310                                                     AnyCType typed_array_arg,
311                                                     AnyCType options) {
312     AnyCType ret;
313 #ifdef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
314     ret.double_value = AddAllTypedArrayFastCallback(
315         receiver.object_value, should_fallback.bool_value,
316         *AnyCTypeToTypedArray<T>(typed_array_arg), *options.options_value);
317 #else
318     ret.int32_value = AddAllTypedArrayFastCallback(
319         receiver.object_value, should_fallback.bool_value,
320         *AnyCTypeToTypedArray<T>(typed_array_arg), *options.options_value);
321 #endif  // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
322     return ret;
323   }
324 #endif  //  V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
325   template <typename T>
AddAllTypedArrayFastCallback(Local<Object> receiver,bool should_fallback,const FastApiTypedArray<T> & typed_array_arg,FastApiCallbackOptions & options)326   static Type AddAllTypedArrayFastCallback(
327       Local<Object> receiver, bool should_fallback,
328       const FastApiTypedArray<T>& typed_array_arg,
329       FastApiCallbackOptions& options) {
330     FastCApiObject* self = UnwrapObject(receiver);
331     CHECK_SELF_OR_FALLBACK(0);
332     self->fast_call_count_++;
333 
334     if (should_fallback) {
335       options.fallback = true;
336       return 0;
337     }
338 
339     T sum = 0;
340     for (unsigned i = 0; i < typed_array_arg.length(); ++i) {
341       sum += typed_array_arg.get(i);
342     }
343     return static_cast<Type>(sum);
344   }
AddAllTypedArraySlowCallback(const FunctionCallbackInfo<Value> & args)345   static void AddAllTypedArraySlowCallback(
346       const FunctionCallbackInfo<Value>& args) {
347     Isolate* isolate = args.GetIsolate();
348 
349     FastCApiObject* self = UnwrapObject(args.This());
350     CHECK_SELF_OR_THROW();
351     self->slow_call_count_++;
352 
353     HandleScope handle_scope(isolate);
354 
355     if (args.Length() < 2) {
356       isolate->ThrowError("This method expects at least 2 arguments.");
357       return;
358     }
359     if (!args[1]->IsTypedArray()) {
360       isolate->ThrowError(
361           "This method expects a TypedArray as a second argument.");
362       return;
363     }
364 
365     Local<TypedArray> typed_array_arg = args[1].As<TypedArray>();
366     size_t length = typed_array_arg->Length();
367 
368     void* data = typed_array_arg->Buffer()->GetBackingStore()->Data();
369     if (typed_array_arg->IsInt32Array() || typed_array_arg->IsUint32Array() ||
370         typed_array_arg->IsBigInt64Array() ||
371         typed_array_arg->IsBigUint64Array()) {
372       int64_t sum = 0;
373       for (unsigned i = 0; i < length; ++i) {
374         if (typed_array_arg->IsInt32Array()) {
375           sum += static_cast<int32_t*>(data)[i];
376         } else if (typed_array_arg->IsUint32Array()) {
377           sum += static_cast<uint32_t*>(data)[i];
378         } else if (typed_array_arg->IsBigInt64Array()) {
379           sum += static_cast<int64_t*>(data)[i];
380         } else if (typed_array_arg->IsBigUint64Array()) {
381           sum += static_cast<uint64_t*>(data)[i];
382         }
383       }
384       args.GetReturnValue().Set(Number::New(isolate, sum));
385     } else if (typed_array_arg->IsFloat32Array() ||
386                typed_array_arg->IsFloat64Array()) {
387       double sum = 0;
388       for (unsigned i = 0; i < length; ++i) {
389         if (typed_array_arg->IsFloat32Array()) {
390           sum += static_cast<float*>(data)[i];
391         } else if (typed_array_arg->IsFloat64Array()) {
392           sum += static_cast<double*>(data)[i];
393         }
394       }
395       args.GetReturnValue().Set(Number::New(isolate, sum));
396     } else {
397       isolate->ThrowError("TypedArray type is not supported.");
398       return;
399     }
400   }
401 
AddAllIntInvalidCallback(Local<Object> receiver,bool should_fallback,int32_t arg_i32,FastApiCallbackOptions & options)402   static int32_t AddAllIntInvalidCallback(Local<Object> receiver,
403                                           bool should_fallback, int32_t arg_i32,
404                                           FastApiCallbackOptions& options) {
405     // This should never be called
406     UNREACHABLE();
407   }
408 
409 #ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
Add32BitIntFastCallbackPatch(AnyCType receiver,AnyCType should_fallback,AnyCType arg_i32,AnyCType arg_u32,AnyCType options)410   static AnyCType Add32BitIntFastCallbackPatch(AnyCType receiver,
411                                                AnyCType should_fallback,
412                                                AnyCType arg_i32,
413                                                AnyCType arg_u32,
414                                                AnyCType options) {
415     AnyCType ret;
416     ret.int32_value = Add32BitIntFastCallback(
417         receiver.object_value, should_fallback.bool_value, arg_i32.int32_value,
418         arg_u32.uint32_value, *options.options_value);
419     return ret;
420   }
421 #endif  //  V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
422 
Add32BitIntFastCallback(v8::Local<v8::Object> receiver,bool should_fallback,int32_t arg_i32,uint32_t arg_u32,FastApiCallbackOptions & options)423   static int Add32BitIntFastCallback(v8::Local<v8::Object> receiver,
424                                      bool should_fallback, int32_t arg_i32,
425                                      uint32_t arg_u32,
426                                      FastApiCallbackOptions& options) {
427     FastCApiObject* self = UnwrapObject(receiver);
428     CHECK_SELF_OR_FALLBACK(0);
429     self->fast_call_count_++;
430 
431     if (should_fallback) {
432       options.fallback = true;
433       return 0;
434     }
435 
436     return arg_i32 + arg_u32;
437   }
Add32BitIntSlowCallback(const FunctionCallbackInfo<Value> & args)438   static void Add32BitIntSlowCallback(const FunctionCallbackInfo<Value>& args) {
439     Isolate* isolate = args.GetIsolate();
440 
441     FastCApiObject* self = UnwrapObject(args.This());
442     CHECK_SELF_OR_THROW();
443     self->slow_call_count_++;
444 
445     HandleScope handle_scope(isolate);
446 
447     double sum = 0;
448     if (args.Length() > 1 && args[1]->IsNumber()) {
449       sum += args[1]->Int32Value(isolate->GetCurrentContext()).FromJust();
450     }
451     if (args.Length() > 2 && args[2]->IsNumber()) {
452       sum += args[2]->Uint32Value(isolate->GetCurrentContext()).FromJust();
453     }
454 
455     args.GetReturnValue().Set(Number::New(isolate, sum));
456   }
457 
458 #ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
AddAll32BitIntFastCallback_8ArgsPatch(AnyCType receiver,AnyCType should_fallback,AnyCType arg1_i32,AnyCType arg2_i32,AnyCType arg3_i32,AnyCType arg4_u32,AnyCType arg5_u32,AnyCType arg6_u32,AnyCType arg7_u32,AnyCType arg8_u32,AnyCType options)459   static AnyCType AddAll32BitIntFastCallback_8ArgsPatch(
460       AnyCType receiver, AnyCType should_fallback, AnyCType arg1_i32,
461       AnyCType arg2_i32, AnyCType arg3_i32, AnyCType arg4_u32,
462       AnyCType arg5_u32, AnyCType arg6_u32, AnyCType arg7_u32,
463       AnyCType arg8_u32, AnyCType options) {
464     AnyCType ret;
465     ret.int32_value = AddAll32BitIntFastCallback_8Args(
466         receiver.object_value, should_fallback.bool_value, arg1_i32.int32_value,
467         arg2_i32.int32_value, arg3_i32.int32_value, arg4_u32.uint32_value,
468         arg5_u32.uint32_value, arg6_u32.uint32_value, arg7_u32.uint32_value,
469         arg8_u32.uint32_value, *options.options_value);
470     return ret;
471   }
AddAll32BitIntFastCallback_6ArgsPatch(AnyCType receiver,AnyCType should_fallback,AnyCType arg1_i32,AnyCType arg2_i32,AnyCType arg3_i32,AnyCType arg4_u32,AnyCType arg5_u32,AnyCType arg6_u32,AnyCType options)472   static AnyCType AddAll32BitIntFastCallback_6ArgsPatch(
473       AnyCType receiver, AnyCType should_fallback, AnyCType arg1_i32,
474       AnyCType arg2_i32, AnyCType arg3_i32, AnyCType arg4_u32,
475       AnyCType arg5_u32, AnyCType arg6_u32, AnyCType options) {
476     AnyCType ret;
477     ret.int32_value = AddAll32BitIntFastCallback_6Args(
478         receiver.object_value, should_fallback.bool_value, arg1_i32.int32_value,
479         arg2_i32.int32_value, arg3_i32.int32_value, arg4_u32.uint32_value,
480         arg5_u32.uint32_value, arg6_u32.uint32_value, *options.options_value);
481     return ret;
482   }
AddAll32BitIntFastCallback_5ArgsPatch(AnyCType receiver,AnyCType should_fallback,AnyCType arg1_i32,AnyCType arg2_i32,AnyCType arg3_i32,AnyCType arg4_u32,AnyCType arg5_u32,AnyCType options)483   static AnyCType AddAll32BitIntFastCallback_5ArgsPatch(
484       AnyCType receiver, AnyCType should_fallback, AnyCType arg1_i32,
485       AnyCType arg2_i32, AnyCType arg3_i32, AnyCType arg4_u32,
486       AnyCType arg5_u32, AnyCType options) {
487     AnyCType arg6;
488     arg6.uint32_value = 0;
489     return AddAll32BitIntFastCallback_6ArgsPatch(
490         receiver, should_fallback, arg1_i32, arg2_i32, arg3_i32, arg4_u32,
491         arg5_u32, arg6, options);
492   }
493 #endif  //  V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
494 
AddAll32BitIntFastCallback_8Args(Local<Object> receiver,bool should_fallback,int32_t arg1_i32,int32_t arg2_i32,int32_t arg3_i32,uint32_t arg4_u32,uint32_t arg5_u32,uint32_t arg6_u32,uint32_t arg7_u32,uint32_t arg8_u32,FastApiCallbackOptions & options)495   static int AddAll32BitIntFastCallback_8Args(
496       Local<Object> receiver, bool should_fallback, int32_t arg1_i32,
497       int32_t arg2_i32, int32_t arg3_i32, uint32_t arg4_u32, uint32_t arg5_u32,
498       uint32_t arg6_u32, uint32_t arg7_u32, uint32_t arg8_u32,
499       FastApiCallbackOptions& options) {
500     FastCApiObject* self = UnwrapObject(receiver);
501     CHECK_SELF_OR_FALLBACK(0);
502     self->fast_call_count_++;
503 
504     if (should_fallback) {
505       options.fallback = true;
506       return 0;
507     }
508 
509     int64_t result = static_cast<int64_t>(arg1_i32) + arg2_i32 + arg3_i32 +
510                      arg4_u32 + arg5_u32 + arg6_u32 + arg7_u32 + arg8_u32;
511     if (result > INT_MAX) return INT_MAX;
512     if (result < INT_MIN) return INT_MIN;
513     return static_cast<int>(result);
514   }
AddAll32BitIntFastCallback_6Args(Local<Object> receiver,bool should_fallback,int32_t arg1_i32,int32_t arg2_i32,int32_t arg3_i32,uint32_t arg4_u32,uint32_t arg5_u32,uint32_t arg6_u32,FastApiCallbackOptions & options)515   static int AddAll32BitIntFastCallback_6Args(
516       Local<Object> receiver, bool should_fallback, int32_t arg1_i32,
517       int32_t arg2_i32, int32_t arg3_i32, uint32_t arg4_u32, uint32_t arg5_u32,
518       uint32_t arg6_u32, FastApiCallbackOptions& options) {
519     FastCApiObject* self = UnwrapObject(receiver);
520     CHECK_SELF_OR_FALLBACK(0);
521     self->fast_call_count_++;
522 
523     if (should_fallback) {
524       options.fallback = true;
525       return 0;
526     }
527 
528     int64_t result = static_cast<int64_t>(arg1_i32) + arg2_i32 + arg3_i32 +
529                      arg4_u32 + arg5_u32 + arg6_u32;
530     if (result > INT_MAX) return INT_MAX;
531     if (result < INT_MIN) return INT_MIN;
532     return static_cast<int>(result);
533   }
AddAll32BitIntFastCallback_5Args(Local<Object> receiver,bool should_fallback,int32_t arg1_i32,int32_t arg2_i32,int32_t arg3_i32,uint32_t arg4_u32,uint32_t arg5_u32,FastApiCallbackOptions & options)534   static int AddAll32BitIntFastCallback_5Args(
535       Local<Object> receiver, bool should_fallback, int32_t arg1_i32,
536       int32_t arg2_i32, int32_t arg3_i32, uint32_t arg4_u32, uint32_t arg5_u32,
537       FastApiCallbackOptions& options) {
538     return AddAll32BitIntFastCallback_6Args(receiver, should_fallback, arg1_i32,
539                                             arg2_i32, arg3_i32, arg4_u32,
540                                             arg5_u32, 0, options);
541   }
AddAll32BitIntSlowCallback(const FunctionCallbackInfo<Value> & args)542   static void AddAll32BitIntSlowCallback(
543       const FunctionCallbackInfo<Value>& args) {
544     Isolate* isolate = args.GetIsolate();
545 
546     FastCApiObject* self = UnwrapObject(args.This());
547     CHECK_SELF_OR_THROW();
548     self->slow_call_count_++;
549 
550     HandleScope handle_scope(isolate);
551 
552     Local<Context> context = isolate->GetCurrentContext();
553     double sum = 0;
554     if (args.Length() > 1 && args[1]->IsNumber()) {
555       sum += args[1]->Int32Value(context).FromJust();
556     }
557     if (args.Length() > 2 && args[2]->IsNumber()) {
558       sum += args[2]->Int32Value(context).FromJust();
559     }
560     if (args.Length() > 3 && args[3]->IsNumber()) {
561       sum += args[3]->Int32Value(context).FromJust();
562     }
563     if (args.Length() > 4 && args[4]->IsNumber()) {
564       sum += args[4]->Uint32Value(context).FromJust();
565     }
566     if (args.Length() > 5 && args[5]->IsNumber()) {
567       sum += args[5]->Uint32Value(context).FromJust();
568     }
569     if (args.Length() > 6 && args[6]->IsNumber()) {
570       sum += args[6]->Uint32Value(context).FromJust();
571     }
572     if (args.Length() > 7 && args[7]->IsNumber() && args[8]->IsNumber()) {
573       sum += args[7]->Uint32Value(context).FromJust();
574       sum += args[8]->Uint32Value(context).FromJust();
575     }
576 
577     args.GetReturnValue().Set(Number::New(isolate, sum));
578   }
579 
IsFastCApiObjectFastCallback(v8::Local<v8::Object> receiver,bool should_fallback,v8::Local<v8::Value> arg,FastApiCallbackOptions & options)580   static bool IsFastCApiObjectFastCallback(v8::Local<v8::Object> receiver,
581                                            bool should_fallback,
582                                            v8::Local<v8::Value> arg,
583                                            FastApiCallbackOptions& options) {
584     FastCApiObject* self = UnwrapObject(receiver);
585     CHECK_SELF_OR_FALLBACK(false);
586     self->fast_call_count_++;
587 
588     if (should_fallback) {
589       options.fallback = true;
590       return false;
591     }
592 
593     if (!arg->IsObject()) {
594       return false;
595     }
596     Local<Object> object = arg.As<Object>();
597     if (!IsValidApiObject(object)) return false;
598 
599     internal::Isolate* i_isolate =
600         internal::IsolateFromNeverReadOnlySpaceObject(
601             *reinterpret_cast<internal::Address*>(*object));
602     CHECK_NOT_NULL(i_isolate);
603     Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
604     HandleScope handle_scope(isolate);
605     return PerIsolateData::Get(isolate)
606         ->GetTestApiObjectCtor()
607         ->IsLeafTemplateForApiObject(object);
608   }
IsFastCApiObjectSlowCallback(const FunctionCallbackInfo<Value> & args)609   static void IsFastCApiObjectSlowCallback(
610       const FunctionCallbackInfo<Value>& args) {
611     Isolate* isolate = args.GetIsolate();
612 
613     FastCApiObject* self = UnwrapObject(args.This());
614     CHECK_SELF_OR_THROW();
615     self->slow_call_count_++;
616 
617     HandleScope handle_scope(isolate);
618 
619     bool result = false;
620     if (args.Length() < 2) {
621       args.GetIsolate()->ThrowError(
622           "is_valid_api_object should be called with 2 arguments");
623       return;
624     }
625     if (args[1]->IsObject()) {
626       Local<Object> object = args[1].As<Object>();
627       if (!IsValidApiObject(object)) {
628         result = false;
629       } else {
630         result = PerIsolateData::Get(args.GetIsolate())
631                      ->GetTestApiObjectCtor()
632                      ->IsLeafTemplateForApiObject(object);
633       }
634     }
635 
636     args.GetReturnValue().Set(Boolean::New(isolate, result));
637   }
638 
FastCallCount(const FunctionCallbackInfo<Value> & args)639   static void FastCallCount(const FunctionCallbackInfo<Value>& args) {
640     FastCApiObject* self = UnwrapObject(args.This());
641     CHECK_SELF_OR_THROW();
642     args.GetReturnValue().Set(
643         Number::New(args.GetIsolate(), self->fast_call_count()));
644   }
SlowCallCount(const FunctionCallbackInfo<Value> & args)645   static void SlowCallCount(const FunctionCallbackInfo<Value>& args) {
646     FastCApiObject* self = UnwrapObject(args.This());
647     CHECK_SELF_OR_THROW();
648     args.GetReturnValue().Set(
649         Number::New(args.GetIsolate(), self->slow_call_count()));
650   }
ResetCounts(const FunctionCallbackInfo<Value> & args)651   static void ResetCounts(const FunctionCallbackInfo<Value>& args) {
652     FastCApiObject* self = UnwrapObject(args.This());
653     CHECK_SELF_OR_THROW();
654     self->reset_counts();
655     args.GetReturnValue().Set(Undefined(args.GetIsolate()));
656   }
SupportsFPParams(const FunctionCallbackInfo<Value> & args)657   static void SupportsFPParams(const FunctionCallbackInfo<Value>& args) {
658     FastCApiObject* self = UnwrapObject(args.This());
659     CHECK_SELF_OR_THROW();
660     args.GetReturnValue().Set(self->supports_fp_params_);
661   }
662 
fast_call_count() const663   int fast_call_count() const { return fast_call_count_; }
slow_call_count() const664   int slow_call_count() const { return slow_call_count_; }
reset_counts()665   void reset_counts() {
666     fast_call_count_ = 0;
667     slow_call_count_ = 0;
668   }
669 
670   static const int kV8WrapperObjectIndex = 1;
671 
672  private:
IsValidApiObject(Local<Object> object)673   static bool IsValidApiObject(Local<Object> object) {
674     i::Address addr = *reinterpret_cast<i::Address*>(*object);
675     auto instance_type = i::Internals::GetInstanceType(addr);
676     return (base::IsInRange(instance_type, i::Internals::kFirstJSApiObjectType,
677                             i::Internals::kLastJSApiObjectType) ||
678             instance_type == i::Internals::kJSSpecialApiObjectType);
679   }
UnwrapObject(Local<Object> object)680   static FastCApiObject* UnwrapObject(Local<Object> object) {
681     if (!IsValidApiObject(object)) {
682       return nullptr;
683     }
684     FastCApiObject* wrapped = reinterpret_cast<FastCApiObject*>(
685         object->GetAlignedPointerFromInternalField(kV8WrapperObjectIndex));
686     CHECK_NOT_NULL(wrapped);
687     return wrapped;
688   }
689   int fast_call_count_ = 0, slow_call_count_ = 0;
690 #ifdef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
691   bool supports_fp_params_ = true;
692 #else   // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
693   bool supports_fp_params_ = false;
694 #endif  // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
695 };
696 
697 #undef CHECK_SELF_OR_THROW
698 #undef CHECK_SELF_OR_FALLBACK
699 
700 // The object is statically initialized for simplicity, typically the embedder
701 // will take care of managing their C++ objects lifetime.
702 thread_local FastCApiObject kFastCApiObject;
703 }  // namespace
704 
705 // static
instance()706 FastCApiObject& FastCApiObject::instance() { return kFastCApiObject; }
707 
CreateFastCAPIObject(const FunctionCallbackInfo<Value> & info)708 void CreateFastCAPIObject(const FunctionCallbackInfo<Value>& info) {
709   if (!info.IsConstructCall()) {
710     info.GetIsolate()->ThrowError(
711         "FastCAPI helper must be constructed with new.");
712     return;
713   }
714   Local<Object> api_object = info.Holder();
715   api_object->SetAlignedPointerInInternalField(
716       FastCApiObject::kV8WrapperObjectIndex,
717       reinterpret_cast<void*>(&kFastCApiObject));
718   api_object->SetAccessorProperty(
719       String::NewFromUtf8Literal(info.GetIsolate(), "supports_fp_params"),
720       FunctionTemplate::New(info.GetIsolate(), FastCApiObject::SupportsFPParams)
721           ->GetFunction(api_object->GetCreationContext().ToLocalChecked())
722           .ToLocalChecked());
723 }
724 
CreateTestFastCApiTemplate(Isolate * isolate)725 Local<FunctionTemplate> Shell::CreateTestFastCApiTemplate(Isolate* isolate) {
726   Local<FunctionTemplate> api_obj_ctor =
727       FunctionTemplate::New(isolate, CreateFastCAPIObject);
728   PerIsolateData::Get(isolate)->SetTestApiObjectCtor(api_obj_ctor);
729   Local<Signature> signature = Signature::New(isolate, api_obj_ctor);
730   {
731     CFunction add_all_c_func =
732         CFunction::Make(FastCApiObject::AddAllFastCallback V8_IF_USE_SIMULATOR(
733             FastCApiObject::AddAllFastCallbackPatch));
734     api_obj_ctor->PrototypeTemplate()->Set(
735         isolate, "add_all",
736         FunctionTemplate::New(isolate, FastCApiObject::AddAllSlowCallback,
737                               Local<Value>(), signature, 1,
738                               ConstructorBehavior::kThrow,
739                               SideEffectType::kHasSideEffect, &add_all_c_func));
740 
741     CFunction add_all_seq_c_func = CFunction::Make(
742         FastCApiObject::AddAllSequenceFastCallback V8_IF_USE_SIMULATOR(
743             FastCApiObject::AddAllSequenceFastCallbackPatch));
744     api_obj_ctor->PrototypeTemplate()->Set(
745         isolate, "add_all_sequence",
746         FunctionTemplate::New(
747             isolate, FastCApiObject::AddAllSequenceSlowCallback, Local<Value>(),
748             signature, 1, ConstructorBehavior::kThrow,
749             SideEffectType::kHasSideEffect, &add_all_seq_c_func));
750 
751     CFunction add_all_int32_typed_array_c_func = CFunction::Make(
752         FastCApiObject::AddAllTypedArrayFastCallback<int32_t>
753             V8_IF_USE_SIMULATOR(
754                 FastCApiObject::AddAllTypedArrayFastCallbackPatch<int32_t>));
755 
756     api_obj_ctor->PrototypeTemplate()->Set(
757         isolate, "add_all_int32_typed_array",
758         FunctionTemplate::New(
759             isolate, FastCApiObject::AddAllTypedArraySlowCallback,
760             Local<Value>(), signature, 1, ConstructorBehavior::kThrow,
761             SideEffectType::kHasSideEffect, &add_all_int32_typed_array_c_func));
762 
763     CFunction add_all_int64_typed_array_c_func = CFunction::Make(
764         FastCApiObject::AddAllTypedArrayFastCallback<int64_t>
765             V8_IF_USE_SIMULATOR(
766                 FastCApiObject::AddAllTypedArrayFastCallbackPatch<int64_t>));
767     api_obj_ctor->PrototypeTemplate()->Set(
768         isolate, "add_all_int64_typed_array",
769         FunctionTemplate::New(
770             isolate, FastCApiObject::AddAllTypedArraySlowCallback,
771             Local<Value>(), signature, 1, ConstructorBehavior::kThrow,
772             SideEffectType::kHasSideEffect, &add_all_int64_typed_array_c_func));
773 
774     CFunction add_all_uint64_typed_array_c_func = CFunction::Make(
775         FastCApiObject::AddAllTypedArrayFastCallback<uint64_t>
776             V8_IF_USE_SIMULATOR(
777                 FastCApiObject::AddAllTypedArrayFastCallbackPatch<uint64_t>));
778     api_obj_ctor->PrototypeTemplate()->Set(
779         isolate, "add_all_uint64_typed_array",
780         FunctionTemplate::New(
781             isolate, FastCApiObject::AddAllTypedArraySlowCallback,
782             Local<Value>(), signature, 1, ConstructorBehavior::kThrow,
783             SideEffectType::kHasSideEffect,
784             &add_all_uint64_typed_array_c_func));
785 
786     CFunction add_all_uint32_typed_array_c_func = CFunction::Make(
787         FastCApiObject::AddAllTypedArrayFastCallback<uint32_t>
788             V8_IF_USE_SIMULATOR(
789                 FastCApiObject::AddAllTypedArrayFastCallbackPatch<uint32_t>));
790     api_obj_ctor->PrototypeTemplate()->Set(
791         isolate, "add_all_uint32_typed_array",
792         FunctionTemplate::New(
793             isolate, FastCApiObject::AddAllTypedArraySlowCallback,
794             Local<Value>(), signature, 1, ConstructorBehavior::kThrow,
795             SideEffectType::kHasSideEffect,
796             &add_all_uint32_typed_array_c_func));
797 
798     CFunction add_all_float32_typed_array_c_func = CFunction::Make(
799         FastCApiObject::AddAllTypedArrayFastCallback<float> V8_IF_USE_SIMULATOR(
800             FastCApiObject::AddAllTypedArrayFastCallbackPatch<float>));
801     api_obj_ctor->PrototypeTemplate()->Set(
802         isolate, "add_all_float32_typed_array",
803         FunctionTemplate::New(
804             isolate, FastCApiObject::AddAllTypedArraySlowCallback,
805             Local<Value>(), signature, 1, ConstructorBehavior::kThrow,
806             SideEffectType::kHasSideEffect,
807             &add_all_float32_typed_array_c_func));
808 
809     CFunction add_all_float64_typed_array_c_func = CFunction::Make(
810         FastCApiObject::AddAllTypedArrayFastCallback<double>
811             V8_IF_USE_SIMULATOR(
812                 FastCApiObject::AddAllTypedArrayFastCallbackPatch<double>));
813     api_obj_ctor->PrototypeTemplate()->Set(
814         isolate, "add_all_float64_typed_array",
815         FunctionTemplate::New(
816             isolate, FastCApiObject::AddAllTypedArraySlowCallback,
817             Local<Value>(), signature, 1, ConstructorBehavior::kThrow,
818             SideEffectType::kHasSideEffect,
819             &add_all_float64_typed_array_c_func));
820 
821     const CFunction add_all_overloads[] = {
822         add_all_uint32_typed_array_c_func,
823         add_all_seq_c_func,
824     };
825     api_obj_ctor->PrototypeTemplate()->Set(
826         isolate, "add_all_overload",
827         FunctionTemplate::NewWithCFunctionOverloads(
828             isolate, FastCApiObject::AddAllSequenceSlowCallback, Local<Value>(),
829             signature, 1, ConstructorBehavior::kThrow,
830             SideEffectType::kHasSideEffect, {add_all_overloads, 2}));
831 
832     CFunction add_all_int_invalid_func =
833         CFunction::Make(FastCApiObject::AddAllIntInvalidCallback);
834     const CFunction add_all_invalid_overloads[] = {
835         add_all_int_invalid_func,
836         add_all_seq_c_func,
837     };
838     api_obj_ctor->PrototypeTemplate()->Set(
839         isolate, "add_all_invalid_overload",
840         FunctionTemplate::NewWithCFunctionOverloads(
841             isolate, FastCApiObject::AddAllSequenceSlowCallback, Local<Value>(),
842             signature, 1, ConstructorBehavior::kThrow,
843             SideEffectType::kHasSideEffect, {add_all_invalid_overloads, 2}));
844 
845     CFunction add_all_32bit_int_8args_c_func = CFunction::Make(
846         FastCApiObject::AddAll32BitIntFastCallback_8Args V8_IF_USE_SIMULATOR(
847             FastCApiObject::AddAll32BitIntFastCallback_8ArgsPatch));
848     CFunction add_all_32bit_int_6args_c_func = CFunction::Make(
849         FastCApiObject::AddAll32BitIntFastCallback_6Args V8_IF_USE_SIMULATOR(
850             FastCApiObject::AddAll32BitIntFastCallback_6ArgsPatch));
851     CFunction add_all_32bit_int_5args_c_func = CFunction::Make(
852         FastCApiObject::AddAll32BitIntFastCallback_5Args V8_IF_USE_SIMULATOR(
853             FastCApiObject::AddAll32BitIntFastCallback_5ArgsPatch));
854     const CFunction c_function_overloads[] = {add_all_32bit_int_6args_c_func,
855                                               add_all_32bit_int_5args_c_func};
856 
857     api_obj_ctor->PrototypeTemplate()->Set(
858         isolate, "overloaded_add_all_32bit_int",
859         FunctionTemplate::NewWithCFunctionOverloads(
860             isolate, FastCApiObject::AddAll32BitIntSlowCallback, Local<Value>(),
861             signature, 1, ConstructorBehavior::kThrow,
862             SideEffectType::kHasSideEffect, {c_function_overloads, 2}));
863 
864     api_obj_ctor->PrototypeTemplate()->Set(
865         isolate, "overloaded_add_all_8args",
866         FunctionTemplate::New(
867             isolate, FastCApiObject::AddAll32BitIntSlowCallback, Local<Value>(),
868             signature, 1, ConstructorBehavior::kThrow,
869             SideEffectType::kHasSideEffect, &add_all_32bit_int_8args_c_func));
870 
871     api_obj_ctor->PrototypeTemplate()->Set(
872         isolate, "overloaded_add_all_32bit_int_no_sig",
873         FunctionTemplate::NewWithCFunctionOverloads(
874             isolate, FastCApiObject::AddAll32BitIntSlowCallback, Local<Value>(),
875             Local<Signature>(), 1, ConstructorBehavior::kThrow,
876             SideEffectType::kHasSideEffect, {c_function_overloads, 2}));
877 
878     CFunction add_all_no_options_c_func = CFunction::Make(
879         FastCApiObject::AddAllFastCallbackNoOptions V8_IF_USE_SIMULATOR(
880             FastCApiObject::AddAllFastCallbackNoOptionsPatch));
881     api_obj_ctor->PrototypeTemplate()->Set(
882         isolate, "add_all_no_options",
883         FunctionTemplate::New(
884             isolate, FastCApiObject::AddAllSlowCallback, Local<Value>(),
885             Local<Signature>(), 1, ConstructorBehavior::kThrow,
886             SideEffectType::kHasSideEffect, &add_all_no_options_c_func));
887 
888     CFunction add_32bit_int_c_func = CFunction::Make(
889         FastCApiObject::Add32BitIntFastCallback V8_IF_USE_SIMULATOR(
890             FastCApiObject::Add32BitIntFastCallbackPatch));
891     api_obj_ctor->PrototypeTemplate()->Set(
892         isolate, "add_32bit_int",
893         FunctionTemplate::New(
894             isolate, FastCApiObject::Add32BitIntSlowCallback, Local<Value>(),
895             signature, 1, ConstructorBehavior::kThrow,
896             SideEffectType::kHasSideEffect, &add_32bit_int_c_func));
897 
898     CFunction is_valid_api_object_c_func =
899         CFunction::Make(FastCApiObject::IsFastCApiObjectFastCallback);
900     api_obj_ctor->PrototypeTemplate()->Set(
901         isolate, "is_fast_c_api_object",
902         FunctionTemplate::New(
903             isolate, FastCApiObject::IsFastCApiObjectSlowCallback,
904             Local<Value>(), signature, 1, ConstructorBehavior::kThrow,
905             SideEffectType::kHasSideEffect, &is_valid_api_object_c_func));
906 
907     api_obj_ctor->PrototypeTemplate()->Set(
908         isolate, "fast_call_count",
909         FunctionTemplate::New(
910             isolate, FastCApiObject::FastCallCount, Local<Value>(), signature,
911             1, ConstructorBehavior::kThrow, SideEffectType::kHasNoSideEffect));
912     api_obj_ctor->PrototypeTemplate()->Set(
913         isolate, "slow_call_count",
914         FunctionTemplate::New(
915             isolate, FastCApiObject::SlowCallCount, Local<Value>(), signature,
916             1, ConstructorBehavior::kThrow, SideEffectType::kHasNoSideEffect));
917     api_obj_ctor->PrototypeTemplate()->Set(
918         isolate, "reset_counts",
919         FunctionTemplate::New(isolate, FastCApiObject::ResetCounts,
920                               Local<Value>(), signature, 1,
921                               ConstructorBehavior::kThrow));
922   }
923   api_obj_ctor->InstanceTemplate()->SetInternalFieldCount(
924       FastCApiObject::kV8WrapperObjectIndex + 1);
925 
926   return api_obj_ctor;
927 }
928 
CreateLeafInterfaceObject(const FunctionCallbackInfo<Value> & info)929 void CreateLeafInterfaceObject(const FunctionCallbackInfo<Value>& info) {
930   if (!info.IsConstructCall()) {
931     info.GetIsolate()->ThrowError(
932         "LeafInterfaceType helper must be constructed with new.");
933   }
934 }
935 
CreateLeafInterfaceTypeTemplate(Isolate * isolate)936 Local<FunctionTemplate> Shell::CreateLeafInterfaceTypeTemplate(
937     Isolate* isolate) {
938   Local<FunctionTemplate> leaf_object_ctor =
939       FunctionTemplate::New(isolate, CreateLeafInterfaceObject);
940   leaf_object_ctor->SetClassName(
941       String::NewFromUtf8Literal(isolate, "LeafInterfaceType"));
942   return leaf_object_ctor;
943 }
944 
945 }  // namespace v8
946