v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
d8-test.cc
Go to the documentation of this file.
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
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.
13// The fast_c_api object also supports querying the number of fast/slow calls
14// and resetting these counters.
15
16namespace v8 {
17namespace {
18
19#define CHECK_SELF_OR_THROW_FAST_OPTIONS(return_value) \
20 if (!self) { \
21 HandleScope handle_scope(options.isolate); \
22 options.isolate->ThrowError( \
23 "This method is not defined on objects inheriting from FastCAPI."); \
24 return return_value; \
25 }
26
27#define CHECK_SELF_OR_THROW_FAST(return_value) \
28 if (!self) { \
29 receiver->GetIsolate()->ThrowError( \
30 "This method is not defined on objects inheriting from FastCAPI."); \
31 return return_value; \
32 }
33
34#define CHECK_SELF_OR_THROW_SLOW() \
35 if (!self) { \
36 info.GetIsolate()->ThrowError( \
37 "This method is not defined on objects inheriting from FastCAPI."); \
38 return; \
39 }
40
41class FastCApiObject {
42 public:
43 static FastCApiObject& instance();
44
45#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
46 static AnyCType ThrowNoFallbackFastCallbackPatch(AnyCType receiver) {
47 AnyCType ret;
48 ThrowNoFallbackFastCallback(receiver.object_value);
49 return ret;
50 }
51
52#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
53
54 static int ThrowNoFallbackFastCallback(Local<Object> receiver) {
55 FastCApiObject* self = UnwrapObject(receiver);
56 if (!self) {
57 self = &FastCApiObject::instance();
58 }
59 self->fast_call_count_++;
61 v8::HandleScope scope(isolate);
62 v8::Local<v8::Context> context = isolate->GetCurrentContext();
63 v8::Context::Scope context_scope(context);
64 isolate->ThrowError("Exception from fast callback");
65 return 0;
66 }
67
68 static void ThrowFallbackSlowCallback(
69 const FunctionCallbackInfo<Value>& info) {
71 FastCApiObject* self = UnwrapObject(info.This());
73 self->slow_call_count_++;
74
75 info.GetIsolate()->ThrowError("Exception from slow callback");
76 }
77
78#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
79 static AnyCType CopyStringFastCallbackPatch(AnyCType receiver,
80 AnyCType source, AnyCType out,
81 AnyCType options) {
82 AnyCType ret;
83 CopyStringFastCallback(receiver.object_value, *source.string_value,
84 out.object_value, *options.options_value);
85 return ret;
86 }
87
88#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
89 static void CopyStringFastCallback(Local<Object> receiver,
90 const FastOneByteString& source,
91 Local<Object> out,
92 FastApiCallbackOptions& options) {
93 FastCApiObject* self = UnwrapObject(receiver);
94 self->fast_call_count_++;
95
96 HandleScope handle_scope(options.isolate);
97 if (!out->IsUint8Array()) {
98 options.isolate->ThrowError(
99 "Invalid parameter, the second parameter has to be a a Uint8Array.");
100 return;
101 }
102 Local<Uint8Array> array = out.As<Uint8Array>();
103 if (array->Length() < source.length) {
104 options.isolate->ThrowError(
105 "Invalid parameter, destination array is too small.");
106 return;
107 }
108 uint8_t* memory =
109 reinterpret_cast<uint8_t*>(out.As<Uint8Array>()->Buffer()->Data());
110 memcpy(memory, source.data, source.length);
111 }
112
113 static void CopyStringSlowCallback(const FunctionCallbackInfo<Value>& info) {
114 FastCApiObject* self = UnwrapObject(info.This());
116 self->slow_call_count_++;
117 }
118#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
119 static AnyCType AddAllFastCallbackPatch(AnyCType receiver,
120 AnyCType arg_i32, AnyCType arg_u32,
121 AnyCType arg_i64, AnyCType arg_u64,
122 AnyCType arg_f32, AnyCType arg_f64,
123 AnyCType options) {
124 AnyCType ret;
125 ret.double_value = AddAllFastCallback(
126 receiver.object_value, arg_i32.int32_value, arg_u32.uint32_value,
127 arg_i64.int64_value, arg_u64.uint64_value, arg_f32.float_value,
128 arg_f64.double_value, *options.options_value);
129 return ret;
130 }
131
132#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
133 static double AddAllFastCallback(Local<Object> receiver, int32_t arg_i32,
134 uint32_t arg_u32, int64_t arg_i64,
135 uint64_t arg_u64, float arg_f32,
136 double arg_f64,
137 FastApiCallbackOptions& options) {
138 FastCApiObject* self = UnwrapObject(receiver);
140 self->fast_call_count_++;
141
142 return static_cast<double>(arg_i32) + static_cast<double>(arg_u32) +
143 static_cast<double>(arg_i64) + static_cast<double>(arg_u64) +
144 static_cast<double>(arg_f32) + arg_f64;
145 }
146
147#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
148 static AnyCType AddAllFastCallbackNoOptionsPatch(
149 AnyCType receiver, AnyCType arg_i32, AnyCType arg_u32, AnyCType arg_i64,
150 AnyCType arg_u64, AnyCType arg_f32, AnyCType arg_f64) {
151 AnyCType ret;
152 ret.double_value = AddAllFastCallbackNoOptions(
153 receiver.object_value, arg_i32.int32_value, arg_u32.uint32_value,
154 arg_i64.int64_value, arg_u64.uint64_value, arg_f32.float_value,
155 arg_f64.double_value);
156 return ret;
157 }
158#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
159 static double AddAllFastCallbackNoOptions(Local<Object> receiver,
160 int32_t arg_i32, uint32_t arg_u32,
161 int64_t arg_i64, uint64_t arg_u64,
162 float arg_f32, double arg_f64) {
163 FastCApiObject* self = UnwrapObject(receiver);
164 if (!self) {
165 self = &FastCApiObject::instance();
166 }
167 self->fast_call_count_++;
168
169 return static_cast<double>(arg_i32) + static_cast<double>(arg_u32) +
170 static_cast<double>(arg_i64) + static_cast<double>(arg_u64) +
171 static_cast<double>(arg_f32) + arg_f64;
172 }
173
174 static void AddAllSlowCallback(const FunctionCallbackInfo<Value>& info) {
175 Isolate* isolate = info.GetIsolate();
176
177 FastCApiObject* self = UnwrapObject(info.This());
179 self->slow_call_count_++;
180
181 HandleScope handle_scope(isolate);
182
183 double sum = 0;
184 if (info.Length() > 0 && info[0]->IsNumber()) {
185 sum += info[0]->Int32Value(isolate->GetCurrentContext()).FromJust();
186 }
187 if (info.Length() > 1 && info[1]->IsNumber()) {
188 sum += info[1]->Uint32Value(isolate->GetCurrentContext()).FromJust();
189 }
190 if (info.Length() > 2 && info[2]->IsNumber()) {
191 sum += info[2]->IntegerValue(isolate->GetCurrentContext()).FromJust();
192 }
193 if (info.Length() > 3 && info[3]->IsNumber()) {
194 sum += info[3]->IntegerValue(isolate->GetCurrentContext()).FromJust();
195 }
196 if (info.Length() > 4 && info[4]->IsNumber()) {
197 sum += info[4]->NumberValue(isolate->GetCurrentContext()).FromJust();
198 } else {
199 sum += std::numeric_limits<double>::quiet_NaN();
200 }
201 if (info.Length() > 5 && info[5]->IsNumber()) {
202 sum += info[5]->NumberValue(isolate->GetCurrentContext()).FromJust();
203 } else {
204 sum += std::numeric_limits<double>::quiet_NaN();
205 }
206
207 info.GetReturnValue().Set(Number::New(isolate, sum));
208 }
209
210#ifdef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
211 typedef double Type;
212#else
213 typedef int32_t Type;
214#endif // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
215#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
216 static AnyCType AddAllSequenceFastCallbackPatch(AnyCType receiver,
217 AnyCType seq_arg,
218 AnyCType options) {
219 AnyCType ret;
220#ifdef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
221 ret.double_value = AddAllSequenceFastCallback(
222 receiver.object_value, seq_arg.sequence_value, *options.options_value);
223#else
224 ret.int32_value = AddAllSequenceFastCallback(
225 receiver.object_value, seq_arg.sequence_value, *options.options_value);
226#endif // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
227 return ret;
228 }
229#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
230
231 static Type AddAllSequenceJSArrayHelper(v8::Isolate* isolate,
232 Local<Array> seq_arg) {
233 Type sum = 0;
234 uint32_t length = seq_arg->Length();
235 if (length > 1024) {
236 isolate->ThrowError(
237 "Invalid length of array, must be between 0 and 1024.");
238 return sum;
239 }
240
241 for (uint32_t i = 0; i < length; ++i) {
242 v8::MaybeLocal<v8::Value> maybe_element =
243 seq_arg->Get(isolate->GetCurrentContext(),
245 if (maybe_element.IsEmpty()) return sum;
246
247 v8::Local<v8::Value> element = maybe_element.ToLocalChecked();
248 if (element->IsNumber()) {
249 double value = element->ToNumber(isolate->GetCurrentContext())
250 .ToLocalChecked()
251 ->Value();
252 sum += value;
253 } else if (element->IsUndefined()) {
254 // Hole: ignore the element.
255 } else {
256 isolate->ThrowError("unexpected element type in JSArray");
257 return sum;
258 }
259 }
260 return sum;
261 }
262
263 static Type AddAllSequenceFastCallback(Local<Object> receiver,
264 Local<Object> seq_arg,
265 FastApiCallbackOptions& options) {
266 if (seq_arg->IsUint32Array()) {
267 return AddAllTypedArrayFastCallback<uint32_t>(receiver, seq_arg, options);
268 }
269
270 FastCApiObject* self = UnwrapObject(receiver);
272 self->fast_call_count_++;
273
274 HandleScope handle_scope(options.isolate);
275 if (!seq_arg->IsArray()) {
276 options.isolate->ThrowError(
277 "This method expects an array as a first argument.");
278 return 0;
279 }
280 Local<Array> array = seq_arg.As<Array>();
281 uint32_t length = array->Length();
282 if (length > 1024) {
283 receiver->GetIsolate()->ThrowError(
284 "Invalid length of array, must be between 0 and 1024.");
285 return 0;
286 }
287
288 Type buffer[1024];
290 CTypeInfoBuilder<Type>::Build().GetId(), Type>(array, buffer, 1024);
291 if (!result) {
292 return AddAllSequenceJSArrayHelper(receiver->GetIsolate(), array);
293 }
294 DCHECK_EQ(array->Length(), length);
295
296 Type sum = 0;
297 for (uint32_t i = 0; i < length; ++i) {
298 sum += buffer[i];
299 }
300
301 return sum;
302 }
303
304 static void AddAllSequenceSlowCallback(
305 const FunctionCallbackInfo<Value>& info) {
307 Isolate* isolate = info.GetIsolate();
308
309 FastCApiObject* self = UnwrapObject(info.This());
311
312 HandleScope handle_scope(isolate);
313
314 if (info.Length() < 1) {
315 self->slow_call_count_++;
316 isolate->ThrowError("This method expects at least 1 arguments.");
317 return;
318 }
319 if (info[0]->IsTypedArray()) {
320 AddAllTypedArraySlowCallback(info);
321 return;
322 }
323 if (info[0]->IsNumber()) {
324 AddAllSlowCallback(info);
325 return;
326 }
327 self->slow_call_count_++;
328 if (info[0]->IsUndefined()) {
329 Type dummy_result = 0;
330 info.GetReturnValue().Set(Number::New(isolate, dummy_result));
331 return;
332 }
333 if (!info[0]->IsArray()) {
334 isolate->ThrowError("This method expects an array as a first argument.");
335 return;
336 }
337 Local<Array> seq_arg = info[0].As<Array>();
338 Type sum = AddAllSequenceJSArrayHelper(isolate, seq_arg);
339
340 info.GetReturnValue().Set(Number::New(isolate, sum));
341 }
342#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
343
344 template <typename T>
345 static AnyCType AddAllTypedArrayFastCallbackPatch(AnyCType receiver,
346 AnyCType typed_array_arg,
347 AnyCType options) {
348 AnyCType ret;
349#ifdef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
350 ret.double_value = AddAllTypedArrayFastCallback<T>(
351 receiver.object_value, typed_array_arg.object_value,
352 *options.options_value);
353#else
354 ret.int32_value = AddAllTypedArrayFastCallback<T>(
355 receiver.object_value, typed_array_arg.object_value,
356 *options.options_value);
357#endif // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
358 return ret;
359 }
360#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
361 template <typename T>
362 static Type AddAllTypedArrayFastCallback(Local<Object> receiver,
363 Local<Value> typed_array_arg,
364 FastApiCallbackOptions& options) {
365 FastCApiObject* self = UnwrapObject(receiver);
367 self->fast_call_count_++;
368
369 HandleScope handle_scope(options.isolate);
370 if (!typed_array_arg->IsTypedArray()) {
371 options.isolate->ThrowError(
372 "This method expects a TypedArray as a first argument.");
373 return 0;
374 }
375 T* memory = reinterpret_cast<T*>(
376 typed_array_arg.As<TypedArray>()->Buffer()->Data());
377 size_t length = typed_array_arg.As<TypedArray>()->ByteLength() / sizeof(T);
378 double sum = 0;
379 for (size_t i = 0; i < length; ++i) {
380 sum += static_cast<double>(memory[i]);
381 }
382 return static_cast<Type>(sum);
383 }
384
385 static void AddAllTypedArraySlowCallback(
386 const FunctionCallbackInfo<Value>& info) {
388 Isolate* isolate = info.GetIsolate();
389
390 FastCApiObject* self = UnwrapObject(info.This());
392 self->slow_call_count_++;
393
394 HandleScope handle_scope(isolate);
395
396 if (info.Length() < 1) {
397 isolate->ThrowError("This method expects at least 1 arguments.");
398 return;
399 }
400 if (!info[0]->IsTypedArray()) {
401 isolate->ThrowError(
402 "This method expects a TypedArray as a second argument.");
403 return;
404 }
405
406 Local<TypedArray> typed_array_arg = info[0].As<TypedArray>();
407 size_t length = typed_array_arg->Length();
408
409 void* data = typed_array_arg->Buffer()->GetBackingStore()->Data();
410 if (typed_array_arg->IsUint8Array() || typed_array_arg->IsInt32Array() ||
411 typed_array_arg->IsUint32Array() ||
412 typed_array_arg->IsBigInt64Array() ||
413 typed_array_arg->IsBigUint64Array()) {
414 int64_t sum = 0;
415 for (unsigned i = 0; i < length; ++i) {
416 if (typed_array_arg->IsUint8Array()) {
417 sum += static_cast<uint8_t*>(data)[i];
418 } else if (typed_array_arg->IsInt32Array()) {
419 sum += static_cast<int32_t*>(data)[i];
420 } else if (typed_array_arg->IsUint32Array()) {
421 sum += static_cast<uint32_t*>(data)[i];
422 } else if (typed_array_arg->IsBigInt64Array()) {
423 sum += static_cast<int64_t*>(data)[i];
424 } else if (typed_array_arg->IsBigUint64Array()) {
425 sum += static_cast<uint64_t*>(data)[i];
426 }
427 }
428 info.GetReturnValue().Set(Number::New(isolate, sum));
429 } else if (typed_array_arg->IsFloat32Array() ||
430 typed_array_arg->IsFloat64Array()) {
431 double sum = 0;
432 for (unsigned i = 0; i < length; ++i) {
433 if (typed_array_arg->IsFloat32Array()) {
434 sum += static_cast<float*>(data)[i];
435 } else if (typed_array_arg->IsFloat64Array()) {
436 sum += static_cast<double*>(data)[i];
437 }
438 }
439 info.GetReturnValue().Set(Number::New(isolate, sum));
440 } else {
441 isolate->ThrowError("TypedArray type is not supported.");
442 return;
443 }
444 }
445
446#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
447 static AnyCType Add32BitIntFastCallbackPatch(AnyCType receiver,
448 AnyCType arg_i32,
449 AnyCType arg_u32,
450 AnyCType options) {
451 AnyCType ret;
452 ret.int32_value =
453 Add32BitIntFastCallback(receiver.object_value, arg_i32.int32_value,
454 arg_u32.uint32_value, *options.options_value);
455 return ret;
456 }
457#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
458
459 static int Add32BitIntFastCallback(v8::Local<v8::Object> receiver,
460 int32_t arg_i32, uint32_t arg_u32,
461 FastApiCallbackOptions& options) {
462 FastCApiObject* self = UnwrapObject(receiver);
464 self->fast_call_count_++;
465
466 return arg_i32 + arg_u32;
467 }
468 static void Add32BitIntSlowCallback(const FunctionCallbackInfo<Value>& info) {
470 Isolate* isolate = info.GetIsolate();
471
472 FastCApiObject* self = UnwrapObject(info.This());
474 self->slow_call_count_++;
475
476 HandleScope handle_scope(isolate);
477
478 double sum = 0;
479 if (info.Length() > 0 && info[0]->IsNumber()) {
480 sum += info[0]->Int32Value(isolate->GetCurrentContext()).FromJust();
481 }
482 if (info.Length() > 1 && info[1]->IsNumber()) {
483 sum += info[1]->Uint32Value(isolate->GetCurrentContext()).FromJust();
484 }
485
486 info.GetReturnValue().Set(Number::New(isolate, sum));
487 }
488
489#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
490 static AnyCType AddAll32BitIntFastCallback_8ArgsPatch(
491 AnyCType receiver, AnyCType arg1_i32, AnyCType arg2_i32,
492 AnyCType arg3_i32, AnyCType arg4_u32, AnyCType arg5_u32,
493 AnyCType arg6_u32, AnyCType arg7_u32, AnyCType arg8_u32,
494 AnyCType options) {
495 AnyCType ret;
496 ret.int32_value = AddAll32BitIntFastCallback_8Args(
497 receiver.object_value, arg1_i32.int32_value, arg2_i32.int32_value,
498 arg3_i32.int32_value, arg4_u32.uint32_value, arg5_u32.uint32_value,
499 arg6_u32.uint32_value, arg7_u32.uint32_value, arg8_u32.uint32_value,
500 *options.options_value);
501 return ret;
502 }
503 static AnyCType AddAll32BitIntFastCallback_6ArgsPatch(
504 AnyCType receiver, AnyCType arg1_i32, AnyCType arg2_i32,
505 AnyCType arg3_i32, AnyCType arg4_u32, AnyCType arg5_u32,
506 AnyCType arg6_u32, AnyCType options) {
507 AnyCType ret;
508 ret.int32_value = AddAll32BitIntFastCallback_6Args(
509 receiver.object_value, arg1_i32.int32_value, arg2_i32.int32_value,
510 arg3_i32.int32_value, arg4_u32.uint32_value, arg5_u32.uint32_value,
511 arg6_u32.uint32_value, *options.options_value);
512 return ret;
513 }
514 static AnyCType AddAll32BitIntFastCallback_5ArgsPatch(
515 AnyCType receiver, AnyCType arg1_i32, AnyCType arg2_i32,
516 AnyCType arg3_i32, AnyCType arg4_u32, AnyCType arg5_u32,
517 AnyCType options) {
518 AnyCType arg6;
519 arg6.uint32_value = 0;
520 return AddAll32BitIntFastCallback_6ArgsPatch(receiver, arg1_i32, arg2_i32,
521 arg3_i32, arg4_u32, arg5_u32,
522 arg6, options);
523 }
524#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
525
526 static int AddAll32BitIntFastCallback_8Args(
527 Local<Object> receiver, int32_t arg1_i32, int32_t arg2_i32,
528 int32_t arg3_i32, uint32_t arg4_u32, uint32_t arg5_u32, uint32_t arg6_u32,
529 uint32_t arg7_u32, uint32_t arg8_u32, FastApiCallbackOptions& options) {
530 FastCApiObject* self = UnwrapObject(receiver);
532 self->fast_call_count_++;
533
534 int64_t result = static_cast<int64_t>(arg1_i32) + arg2_i32 + arg3_i32 +
535 arg4_u32 + arg5_u32 + arg6_u32 + arg7_u32 + arg8_u32;
536 if (result > INT_MAX) return INT_MAX;
537 if (result < INT_MIN) return INT_MIN;
538 return static_cast<int>(result);
539 }
540 static int AddAll32BitIntFastCallback_6Args(
541 Local<Object> receiver, int32_t arg1_i32, int32_t arg2_i32,
542 int32_t arg3_i32, uint32_t arg4_u32, uint32_t arg5_u32, uint32_t arg6_u32,
543 FastApiCallbackOptions& options) {
544 FastCApiObject* self = UnwrapObject(receiver);
546 self->fast_call_count_++;
547
548 int64_t result = static_cast<int64_t>(arg1_i32) + arg2_i32 + arg3_i32 +
549 arg4_u32 + arg5_u32 + arg6_u32;
550 if (result > INT_MAX) return INT_MAX;
551 if (result < INT_MIN) return INT_MIN;
552 return static_cast<int>(result);
553 }
554 static int AddAll32BitIntFastCallback_5Args(
555 Local<Object> receiver, int32_t arg1_i32, int32_t arg2_i32,
556 int32_t arg3_i32, uint32_t arg4_u32, uint32_t arg5_u32,
557 FastApiCallbackOptions& options) {
558 return AddAll32BitIntFastCallback_6Args(
559 receiver, arg1_i32, arg2_i32, arg3_i32, arg4_u32, arg5_u32, 0, options);
560 }
561 static void AddAll32BitIntSlowCallback(
562 const FunctionCallbackInfo<Value>& info) {
564 Isolate* isolate = info.GetIsolate();
565
566 FastCApiObject* self = UnwrapObject(info.This());
568 self->slow_call_count_++;
569
570 HandleScope handle_scope(isolate);
571
572 Local<Context> context = isolate->GetCurrentContext();
573 double sum = 0;
574 if (info.Length() > 0 && info[0]->IsNumber()) {
575 sum += info[0]->Int32Value(context).FromJust();
576 }
577 if (info.Length() > 1 && info[1]->IsNumber()) {
578 sum += info[1]->Int32Value(context).FromJust();
579 }
580 if (info.Length() > 2 && info[2]->IsNumber()) {
581 sum += info[2]->Int32Value(context).FromJust();
582 }
583 if (info.Length() > 3 && info[3]->IsNumber()) {
584 sum += info[3]->Uint32Value(context).FromJust();
585 }
586 if (info.Length() > 4 && info[4]->IsNumber()) {
587 sum += info[4]->Uint32Value(context).FromJust();
588 }
589 if (info.Length() > 5 && info[5]->IsNumber()) {
590 sum += info[5]->Uint32Value(context).FromJust();
591 }
592 if (info.Length() > 7 && info[6]->IsNumber() && info[7]->IsNumber()) {
593 // info[6] and info[7] only get handled together, because we want to
594 // have functions in the list of overloads with 6 parameters and with 8
595 // parameters, but not with 7 parameters.
596 sum += info[6]->Uint32Value(context).FromJust();
597 sum += info[7]->Uint32Value(context).FromJust();
598 }
599
600 info.GetReturnValue().Set(Number::New(isolate, sum));
601 }
602
603#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
604 template <v8::CTypeInfo::Flags flags>
605 static AnyCType AddAllAnnotateFastCallbackPatch(
606 AnyCType receiver, AnyCType arg_i32, AnyCType arg_u32, AnyCType arg_i64,
607 AnyCType arg_u64, AnyCType options) {
608 AnyCType ret;
609 ret.double_value = AddAllAnnotateFastCallback<flags>(
610 receiver.object_value, arg_i32.int32_value, arg_u32.uint32_value,
611 arg_i64.int64_value, arg_u64.uint64_value, *options.options_value);
612 return ret;
613 }
614#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
615
616 template <v8::CTypeInfo::Flags flags>
617 static double AddAllAnnotateFastCallback(Local<Object> receiver,
618 int32_t arg_i32, uint32_t arg_u32,
619 int64_t arg_i64, uint64_t arg_u64,
620 FastApiCallbackOptions& options) {
621 FastCApiObject* self = UnwrapObject(receiver);
622 CHECK_NOT_NULL(self);
623 self->fast_call_count_++;
624
625 return static_cast<double>(arg_i32) + static_cast<double>(arg_u32) +
626 static_cast<double>(arg_i64) + static_cast<double>(arg_u64);
627 }
628
629 static void AddAllAnnotateSlowCallback(
630 const FunctionCallbackInfo<Value>& info) {
632 Isolate* isolate = info.GetIsolate();
633
634 FastCApiObject* self = UnwrapObject(info.This());
636 self->slow_call_count_++;
637
638 HandleScope handle_scope(isolate);
639
640 double sum = 0;
641 if (info.Length() > 1 && info[1]->IsNumber()) {
642 sum += info[1]->Int32Value(isolate->GetCurrentContext()).FromJust();
643 }
644 if (info.Length() > 2 && info[2]->IsNumber()) {
645 sum += info[2]->Uint32Value(isolate->GetCurrentContext()).FromJust();
646 }
647 if (info.Length() > 3 && info[3]->IsNumber()) {
648 sum += info[3]->IntegerValue(isolate->GetCurrentContext()).FromJust();
649 }
650 if (info.Length() > 4 && info[4]->IsNumber()) {
651 sum += info[4]->IntegerValue(isolate->GetCurrentContext()).FromJust();
652 }
653
654 info.GetReturnValue().Set(Number::New(isolate, sum));
655 }
656
657#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
658 static AnyCType EnforceRangeCompareI32Patch(AnyCType receiver,
659 AnyCType real_arg,
660 AnyCType checked_arg,
661 AnyCType options) {
662 AnyCType ret;
663 ret.bool_value = EnforceRangeCompare<int32_t>(
664 receiver.object_value, real_arg.double_value, checked_arg.int32_value,
665 *options.options_value);
666 return ret;
667 }
668 static AnyCType EnforceRangeCompareU32Patch(AnyCType receiver,
669 AnyCType real_arg,
670 AnyCType checked_arg,
671 AnyCType options) {
672 AnyCType ret;
673 ret.bool_value = EnforceRangeCompare<uint32_t>(
674 receiver.object_value, real_arg.double_value, checked_arg.uint32_value,
675 *options.options_value);
676 return ret;
677 }
678 static AnyCType EnforceRangeCompareI64Patch(AnyCType receiver,
679 AnyCType real_arg,
680 AnyCType checked_arg,
681 AnyCType options) {
682 AnyCType ret;
683 ret.bool_value = EnforceRangeCompare<int64_t>(
684 receiver.object_value, real_arg.double_value, checked_arg.int64_value,
685 *options.options_value);
686 return ret;
687 }
688 static AnyCType EnforceRangeCompareU64Patch(AnyCType receiver,
689 AnyCType real_arg,
690 AnyCType checked_arg,
691 AnyCType options) {
692 AnyCType ret;
693 ret.bool_value = EnforceRangeCompare<uint64_t>(
694 receiver.object_value, real_arg.double_value, checked_arg.uint64_value,
695 *options.options_value);
696 return ret;
697 }
698#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
699
700 template <typename IntegerT>
701 static bool EnforceRangeCompare(Local<Object> receiver, double real_arg,
702 IntegerT checked_arg,
703 FastApiCallbackOptions& options) {
704 FastCApiObject* self = UnwrapObject(receiver);
705 CHECK_NOT_NULL(self);
706 self->fast_call_count_++;
707
708 if (!base::IsValueInRangeForNumericType<IntegerT>(real_arg)) {
709 return false;
710 }
711 return static_cast<IntegerT>(real_arg) == checked_arg;
712 }
713
714 template <typename IntegerT>
715 static void EnforceRangeCompareSlowCallback(
716 const FunctionCallbackInfo<Value>& info) {
718 Isolate* isolate = info.GetIsolate();
719
720 FastCApiObject* self = UnwrapObject(info.This());
722 self->slow_call_count_++;
723
724 HandleScope handle_scope(isolate);
725
726 double real_arg = 0;
727 if (info.Length() > 0 && info[0]->IsNumber()) {
728 real_arg = info[0]->NumberValue(isolate->GetCurrentContext()).FromJust();
729 }
730 // Special range checks for int64 and uint64. uint64_max rounds to 2^64 when
731 // converted to double, so 2^64 would be considered within uint64 range even
732 // though it's not. For int64 the same happens with 2^63.
733 bool in_range = base::IsValueInRangeForNumericType<IntegerT>(real_arg);
734 if (in_range) {
735 IntegerT checked_arg = 0;
736 if (info.Length() > 1 && info[1]->IsNumber()) {
737 double checked_arg_as_double =
738 info[1]->NumberValue(isolate->GetCurrentContext()).FromJust();
739 if (base::IsValueInRangeForNumericType<IntegerT>(
740 checked_arg_as_double)) {
741 checked_arg = static_cast<IntegerT>(checked_arg_as_double);
742 }
743 }
744 info.GetReturnValue().Set(static_cast<IntegerT>(real_arg) == checked_arg);
745 } else {
746 info.GetIsolate()->ThrowError("Argument out of range.");
747 }
748 }
749
750#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
751 static AnyCType ClampCompareI32Patch(AnyCType receiver, AnyCType in_range,
752 AnyCType real_arg, AnyCType checked_arg,
753 AnyCType options) {
754 AnyCType ret;
755 ret.double_value = ClampCompare<int32_t>(
756 receiver.object_value, in_range.bool_value, real_arg.double_value,
757 checked_arg.int32_value, *options.options_value);
758 return ret;
759 }
760 static AnyCType ClampCompareU32Patch(AnyCType receiver, AnyCType in_range,
761 AnyCType real_arg, AnyCType checked_arg,
762 AnyCType options) {
763 AnyCType ret;
764 ret.double_value = ClampCompare<uint32_t>(
765 receiver.object_value, in_range.bool_value, real_arg.double_value,
766 checked_arg.uint32_value, *options.options_value);
767 return ret;
768 }
769 static AnyCType ClampCompareI64Patch(AnyCType receiver, AnyCType in_range,
770 AnyCType real_arg, AnyCType checked_arg,
771 AnyCType options) {
772 AnyCType ret;
773 ret.double_value = ClampCompare<int64_t>(
774 receiver.object_value, in_range.bool_value, real_arg.double_value,
775 checked_arg.int64_value, *options.options_value);
776 return ret;
777 }
778 static AnyCType ClampCompareU64Patch(AnyCType receiver, AnyCType in_range,
779 AnyCType real_arg, AnyCType checked_arg,
780 AnyCType options) {
781 AnyCType ret;
782 ret.double_value = ClampCompare<uint64_t>(
783 receiver.object_value, in_range.bool_value, real_arg.double_value,
784 checked_arg.uint64_value, *options.options_value);
785 return ret;
786 }
787#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
788
789 template <typename IntegerT>
790 static double ClampCompareCompute(bool in_range, double real_arg,
791 IntegerT checked_arg) {
792 if (i::v8_flags.fuzzing) {
793 return static_cast<double>(checked_arg);
794 }
795 if (!in_range) {
796 IntegerT lower_bound = std::numeric_limits<IntegerT>::min();
797 IntegerT upper_bound = std::numeric_limits<IntegerT>::max();
798 if (lower_bound < internal::kMinSafeInteger) {
799 lower_bound = static_cast<IntegerT>(internal::kMinSafeInteger);
800 }
801 if (upper_bound > internal::kMaxSafeInteger) {
802 upper_bound = static_cast<IntegerT>(internal::kMaxSafeInteger);
803 }
804 CHECK(!std::isnan(real_arg));
805 if (real_arg < static_cast<double>(lower_bound)) {
806 CHECK_EQ(lower_bound, checked_arg);
807 } else if (real_arg > static_cast<double>(upper_bound)) {
808 CHECK_EQ(upper_bound, checked_arg);
809 } else {
810 FATAL("Expected value to be out of range.");
811 }
812 } else if (!std::isnan(real_arg)) {
813 if (real_arg != checked_arg) {
814 // Check if rounding towards nearest even number happened.
815 double diff = std::fabs(real_arg - checked_arg);
816 CHECK_LE(diff, 0.5);
817 if (diff == 0) {
818 // Check if rounding towards nearest even number happened.
819 CHECK_EQ(0, checked_arg % 2);
820 } else if (checked_arg % 2 == 1) {
821 // Behave as if rounding towards nearest even number *has*
822 // happened (as it does on the fast path).
823 checked_arg += 1;
824 }
825 } else {
826 CHECK_EQ(static_cast<IntegerT>(real_arg), checked_arg);
827 }
828 }
829 return checked_arg;
830 }
831
832 template <typename IntegerT>
833 static double ClampCompare(Local<Object> receiver, bool in_range,
834 double real_arg, IntegerT checked_arg,
835 FastApiCallbackOptions& options) {
836 FastCApiObject* self = UnwrapObject(receiver);
837 CHECK_NOT_NULL(self);
838 self->fast_call_count_++;
839
840 double result = ClampCompareCompute(in_range, real_arg, checked_arg);
841 return static_cast<double>(result);
842 }
843
844 template <typename IntegerT>
845 static void ClampCompareSlowCallback(
846 const FunctionCallbackInfo<Value>& info) {
848 Isolate* isolate = info.GetIsolate();
849
850 FastCApiObject* self = UnwrapObject(info.This());
852 self->slow_call_count_++;
853
854 double real_arg = 0;
855 if (info.Length() > 1 && info[1]->IsNumber()) {
856 real_arg = info[1]->NumberValue(isolate->GetCurrentContext()).FromJust();
857 }
858 double checked_arg_dbl = std::numeric_limits<double>::max();
859 if (info.Length() > 2 && info[2]->IsNumber()) {
860 checked_arg_dbl = info[2].As<Number>()->Value();
861 }
862 bool in_range =
863 info[0]->IsBoolean() && info[0]->BooleanValue(isolate) &&
864 base::IsValueInRangeForNumericType<IntegerT>(real_arg) &&
865 base::IsValueInRangeForNumericType<IntegerT>(checked_arg_dbl);
866
867 IntegerT checked_arg = std::numeric_limits<IntegerT>::max();
868 if (in_range) {
869 if (checked_arg_dbl != std::numeric_limits<double>::max()) {
870 checked_arg = static_cast<IntegerT>(checked_arg_dbl);
871 }
872 double result = ClampCompareCompute(in_range, real_arg, checked_arg);
873 info.GetReturnValue().Set(Number::New(isolate, result));
874 } else {
875 IntegerT clamped = std::numeric_limits<IntegerT>::max();
876 if (std::isnan(checked_arg_dbl) || std::isnan(real_arg)) {
877 clamped = 0;
878 } else {
879 IntegerT lower_bound = std::numeric_limits<IntegerT>::min();
880 IntegerT upper_bound = std::numeric_limits<IntegerT>::max();
881 if (lower_bound < internal::kMinSafeInteger) {
882 lower_bound = static_cast<IntegerT>(internal::kMinSafeInteger);
883 }
884 if (upper_bound > internal::kMaxSafeInteger) {
885 upper_bound = static_cast<IntegerT>(internal::kMaxSafeInteger);
886 }
887
888 clamped = std::clamp(real_arg, static_cast<double>(lower_bound),
889 static_cast<double>(upper_bound));
890 }
891 info.GetReturnValue().Set(Number::New(isolate, clamped));
892 }
893 }
894
895 static bool IsFastCApiObjectFastCallback(v8::Local<v8::Object> receiver,
897 FastApiCallbackOptions& options) {
898 FastCApiObject* self = UnwrapObject(receiver);
900
901 self->fast_call_count_++;
902
903 if (!arg->IsObject()) {
904 return false;
905 }
906 Local<Object> object = arg.As<Object>();
907 if (!IsValidApiObject(object)) return false;
908
909 Isolate* isolate = options.isolate;
910 HandleScope handle_scope(isolate);
911 return PerIsolateData::Get(isolate)
913 ->IsLeafTemplateForApiObject(object);
914 }
915
916 static void IsFastCApiObjectSlowCallback(
917 const FunctionCallbackInfo<Value>& info) {
919 Isolate* isolate = info.GetIsolate();
920
921 FastCApiObject* self = UnwrapObject(info.This());
923 self->slow_call_count_++;
924
925 HandleScope handle_scope(isolate);
926
927 bool result = false;
928 if (info.Length() < 1) {
929 info.GetIsolate()->ThrowError(
930 "is_valid_api_object should be called with an argument");
931 return;
932 }
933 if (info[0]->IsObject()) {
934 Local<Object> object = info[0].As<Object>();
935 if (!IsValidApiObject(object)) {
936 result = false;
937 } else {
938 result = PerIsolateData::Get(info.GetIsolate())
940 ->IsLeafTemplateForApiObject(object);
941 }
942 }
943
944 info.GetReturnValue().Set(result);
945 }
946
947 static bool TestWasmMemoryFastCallback(Local<Object> receiver,
948 uint32_t address,
949 FastApiCallbackOptions& options) {
950 FastCApiObject* self = UnwrapObject(receiver);
952 self->fast_call_count_++;
953
954 if (i::v8_flags.fuzzing) {
955 return true;
956 }
957 v8::Isolate* isolate = receiver->GetIsolate();
958 v8::HandleScope handle_scope(isolate);
959 v8::Local<v8::Context> context = isolate->GetCurrentContext();
960 v8::Local<v8::String> mem_string =
961 v8::String::NewFromUtf8(isolate, "wasm_memory").ToLocalChecked();
963 if (!receiver->Get(context, mem_string).ToLocal(&mem)) {
964 isolate->ThrowError(
965 "wasm_memory was used when the WebAssembly.Memory was not set on the "
966 "receiver.");
967 }
968
971 reinterpret_cast<uint8_t*>(wasm_memory->Buffer()->Data())[address] = 42;
972
973 return true;
974 }
975
976 static void TestWasmMemorySlowCallback(
977 const FunctionCallbackInfo<Value>& info) {
979 FastCApiObject* self = UnwrapObject(info.This());
981 self->slow_call_count_++;
982
983 info.GetIsolate()->ThrowError("should be unreachable from wasm");
984 }
985
986 static void AssertIsExternal(const FunctionCallbackInfo<Value>& info) {
988 FastCApiObject* self = UnwrapObject(info.This());
990
991 Local<Value> value = info[0];
992
993 if (!value->IsExternal()) {
994 info.GetIsolate()->ThrowError("Did not get an external.");
995 }
996 }
997
998 static void* GetPointerFastCallback(Local<Object> receiver,
999 FastApiCallbackOptions& options) {
1000 FastCApiObject* self = UnwrapObject(receiver);
1002 self->fast_call_count_++;
1003
1004 if (i::v8_flags.fuzzing) {
1005 return nullptr;
1006 }
1007 return static_cast<void*>(self);
1008 }
1009
1010 static void GetPointerSlowCallback(const FunctionCallbackInfo<Value>& info) {
1012 Isolate* isolate = info.GetIsolate();
1013 FastCApiObject* self = UnwrapObject(info.This());
1015 self->slow_call_count_++;
1016
1017 if (i::v8_flags.fuzzing) {
1018 info.GetReturnValue().Set(v8::Null(isolate));
1019 return;
1020 }
1021 info.GetReturnValue().Set(External::New(isolate, static_cast<void*>(self)));
1022 }
1023
1024 static void* GetNullPointerFastCallback(Local<Object> receiver,
1025 FastApiCallbackOptions& options) {
1026 FastCApiObject* self = UnwrapObject(receiver);
1028 self->fast_call_count_++;
1029
1030 return nullptr;
1031 }
1032
1033 static void GetNullPointerSlowCallback(
1034 const FunctionCallbackInfo<Value>& info) {
1036 Isolate* isolate = info.GetIsolate();
1037 FastCApiObject* self = UnwrapObject(info.This());
1039 self->slow_call_count_++;
1040
1041 info.GetReturnValue().Set(v8::Null(isolate));
1042 }
1043
1044 static void* PassPointerFastCallback(Local<Object> receiver, void* pointer,
1045 FastApiCallbackOptions& options) {
1046 FastCApiObject* self = UnwrapObject(receiver);
1048 self->fast_call_count_++;
1049
1050 return pointer;
1051 }
1052
1053 static void PassPointerSlowCallback(const FunctionCallbackInfo<Value>& info) {
1055 FastCApiObject* self = UnwrapObject(info.This());
1057 self->slow_call_count_++;
1058
1059 if (info.Length() != 1) {
1060 info.GetIsolate()->ThrowError(
1061 "Invalid number of arguments, expected one.");
1062 return;
1063 }
1064
1065 Local<Value> maybe_external = info[0].As<Value>();
1066
1067 if (maybe_external->IsNull()) {
1068 info.GetReturnValue().Set(maybe_external);
1069 return;
1070 }
1071 if (!maybe_external->IsExternal()) {
1072 info.GetIsolate()->ThrowError("Did not get an external.");
1073 return;
1074 }
1075
1076 Local<External> external = info[0].As<External>();
1077
1078 info.GetReturnValue().Set(external);
1079 }
1080
1081 static bool ComparePointersFastCallback(Local<Object> receiver,
1082 void* pointer_a, void* pointer_b,
1083 FastApiCallbackOptions& options) {
1084 FastCApiObject* self = UnwrapObject(receiver);
1086 self->fast_call_count_++;
1087
1088 return pointer_a == pointer_b;
1089 }
1090
1091 static void ComparePointersSlowCallback(
1092 const FunctionCallbackInfo<Value>& info) {
1094 FastCApiObject* self = UnwrapObject(info.This());
1096 self->slow_call_count_++;
1097
1098 if (info.Length() != 2) {
1099 info.GetIsolate()->ThrowError(
1100 "Invalid number of arguments, expected two.");
1101 return;
1102 }
1103
1104 Local<Value> value_a = info[0];
1105 Local<Value> value_b = info[1];
1106
1107 void* pointer_a;
1108 if (value_a->IsNull()) {
1109 pointer_a = nullptr;
1110 } else if (value_a->IsExternal()) {
1111 pointer_a = value_a.As<External>()->Value();
1112 } else {
1113 info.GetIsolate()->ThrowError(
1114 "Did not get an external as first parameter.");
1115 return;
1116 }
1117
1118 void* pointer_b;
1119 if (value_b->IsNull()) {
1120 pointer_b = nullptr;
1121 } else if (value_b->IsExternal()) {
1122 pointer_b = value_b.As<External>()->Value();
1123 } else {
1124 info.GetIsolate()->ThrowError(
1125 "Did not get an external as second parameter.");
1126 return;
1127 }
1128
1129 info.GetReturnValue().Set(pointer_a == pointer_b);
1130 }
1131
1132 static int64_t sumInt64FastCallback(Local<Object> receiver, int64_t a,
1133 int64_t b,
1134 FastApiCallbackOptions& options) {
1135 FastCApiObject* self = UnwrapObject(receiver);
1137 self->fast_call_count_++;
1138
1139 return a + b;
1140 }
1141
1142 template <typename T>
1143 static bool Convert(double value, T* out_result) {
1144 if (!base::IsValueInRangeForNumericType<T>(value)) return false;
1145 *out_result = static_cast<T>(value);
1146 return true;
1147 }
1148
1149 static void sumInt64AsNumberSlowCallback(
1150 const FunctionCallbackInfo<Value>& info) {
1151 Isolate* isolate = info.GetIsolate();
1152 FastCApiObject* self = UnwrapObject(info.This());
1154 self->slow_call_count_++;
1155
1156 if (info.Length() != 2) {
1157 info.GetIsolate()->ThrowError(
1158 "Invalid number of arguments, expected two.");
1159 return;
1160 }
1161
1162 Local<Value> value_a = info[0];
1163 Local<Value> value_b = info[1];
1164
1165 if (!value_a->IsNumber()) {
1166 info.GetIsolate()->ThrowError("Did not get a number as first parameter.");
1167 return;
1168 }
1169 int64_t a;
1170 if (!Convert(value_a.As<Number>()->Value(), &a)) {
1171 info.GetIsolate()->ThrowError("First number is out of int64_t range.");
1172 return;
1173 }
1174
1175 if (!value_b->IsNumber()) {
1176 info.GetIsolate()->ThrowError(
1177 "Did not get a number as second parameter.");
1178 return;
1179 }
1180 int64_t b;
1181 if (!Convert(value_b.As<Number>()->Value(), &b)) {
1182 info.GetIsolate()->ThrowError("Second number is out of int64_t range.");
1183 return;
1184 }
1185
1186 info.GetReturnValue().Set(Number::New(isolate, static_cast<double>(a + b)));
1187 }
1188
1189 static void sumInt64AsBigIntSlowCallback(
1190 const FunctionCallbackInfo<Value>& info) {
1191 Isolate* isolate = info.GetIsolate();
1192 FastCApiObject* self = UnwrapObject(info.This());
1194 self->slow_call_count_++;
1195
1196 if (info.Length() != 2) {
1197 info.GetIsolate()->ThrowError(
1198 "Invalid number of arguments, expected two.");
1199 return;
1200 }
1201
1202 Local<Value> value_a = info[0];
1203 Local<Value> value_b = info[1];
1204
1205 int64_t a;
1206 if (value_a->IsBigInt()) {
1207 a = static_cast<int64_t>(value_a.As<BigInt>()->Int64Value());
1208 } else {
1209 info.GetIsolate()->ThrowError("Did not get a BigInt as first parameter.");
1210 return;
1211 }
1212
1213 int64_t b;
1214 if (value_b->IsBigInt()) {
1215 b = static_cast<int64_t>(value_b.As<BigInt>()->Int64Value());
1216 } else {
1217 info.GetIsolate()->ThrowError(
1218 "Did not get a BigInt as second parameter.");
1219 return;
1220 }
1221
1222 info.GetReturnValue().Set(BigInt::New(isolate, a + b));
1223 }
1224
1225 static uint64_t sumUint64FastCallback(Local<Object> receiver, uint64_t a,
1226 uint64_t b,
1227 FastApiCallbackOptions& options) {
1228 FastCApiObject* self = UnwrapObject(receiver);
1230 self->fast_call_count_++;
1231 // This CHECK here is unnecessary, but it keeps this function from getting
1232 // merged with `sumInt64FastCallback`. There is a test which relies on
1233 // `sumUint64FastCallback` and `sumInt64FastCallback` being different call
1234 // targets.
1235 CHECK_GT(self->fast_call_count_, 0);
1236 return a + b;
1237 }
1238
1239 static void sumUint64AsNumberSlowCallback(
1240 const FunctionCallbackInfo<Value>& info) {
1241 Isolate* isolate = info.GetIsolate();
1242 FastCApiObject* self = UnwrapObject(info.This());
1244 self->slow_call_count_++;
1245
1246 if (info.Length() != 2) {
1247 info.GetIsolate()->ThrowError(
1248 "Invalid number of arguments, expected two.");
1249 return;
1250 }
1251
1252 Local<Value> value_a = info[0];
1253 Local<Value> value_b = info[1];
1254
1255 if (!value_a->IsNumber()) {
1256 info.GetIsolate()->ThrowError("Did not get a number as first parameter.");
1257 return;
1258 }
1259 uint64_t a;
1260 if (!Convert(value_a.As<Number>()->Value(), &a)) {
1261 info.GetIsolate()->ThrowError("First number is out of uint64_t range.");
1262 return;
1263 }
1264
1265 if (!value_b->IsNumber()) {
1266 info.GetIsolate()->ThrowError(
1267 "Did not get a number as second parameter.");
1268 return;
1269 }
1270 uint64_t b;
1271 if (!Convert(value_b.As<Number>()->Value(), &b)) {
1272 info.GetIsolate()->ThrowError("Second number is out of uint64_t range.");
1273 return;
1274 }
1275
1276 info.GetReturnValue().Set(Number::New(isolate, static_cast<double>(a + b)));
1277 }
1278
1279 static void sumUint64AsBigIntSlowCallback(
1280 const FunctionCallbackInfo<Value>& info) {
1281 Isolate* isolate = info.GetIsolate();
1282 FastCApiObject* self = UnwrapObject(info.This());
1284 self->slow_call_count_++;
1285
1286 if (info.Length() != 2) {
1287 info.GetIsolate()->ThrowError(
1288 "Invalid number of arguments, expected two.");
1289 return;
1290 }
1291
1292 Local<Value> value_a = info[0];
1293 Local<Value> value_b = info[1];
1294
1295 uint64_t a;
1296 if (value_a->IsBigInt()) {
1297 a = static_cast<uint64_t>(value_a.As<BigInt>()->Uint64Value());
1298 } else {
1299 info.GetIsolate()->ThrowError("Did not get a BigInt as first parameter.");
1300 return;
1301 }
1302
1303 uint64_t b;
1304 if (value_b->IsBigInt()) {
1305 b = static_cast<uint64_t>(value_b.As<BigInt>()->Uint64Value());
1306 } else {
1307 info.GetIsolate()->ThrowError(
1308 "Did not get a BigInt as second parameter.");
1309 return;
1310 }
1311
1312 info.GetReturnValue().Set(BigInt::NewFromUnsigned(isolate, a + b));
1313 }
1314
1315 static void AttributeGetterSlowCallback(
1316 const FunctionCallbackInfo<Value>& info) {
1317 FastCApiObject* self = UnwrapObject(info.This());
1318 self->slow_call_count_++;
1319 info.GetReturnValue().Set(self->attribute_value_);
1320 }
1321
1322 static int AttributeGetterFastCallback(Local<Object> receiver,
1323 FastApiCallbackOptions& options) {
1324 FastCApiObject* self = UnwrapObject(receiver);
1326 self->fast_call_count_++;
1327 return self->attribute_value_;
1328 }
1329
1330#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1331 static AnyCType AttributeGetterFastCallbackPatch(AnyCType receiver,
1332 AnyCType options) {
1333 AnyCType ret;
1334 ret.int32_value = AttributeGetterFastCallback(receiver.object_value,
1335 *options.options_value);
1336 return ret;
1337 }
1338#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1339
1340 static void AttributeSetterSlowCallback(
1341 const FunctionCallbackInfo<Value>& info) {
1342 FastCApiObject* self = UnwrapObject(info.This());
1343 self->slow_call_count_++;
1344 if (info.Length() < 1 || !info[0]->IsNumber()) {
1345 info.GetIsolate()->ThrowError(
1346 "The attribute requires a number as a new value");
1347 return;
1348 }
1349 double double_val =
1350 info[0]->NumberValue(info.GetIsolate()->GetCurrentContext()).FromJust();
1351 if (!base::IsValueInRangeForNumericType<int>(double_val)) {
1352 info.GetIsolate()->ThrowError(
1353 "New value of attribute is not within int32 range");
1354 return;
1355 }
1356 self->attribute_value_ = static_cast<int>(double_val);
1357 }
1358
1359 static void AttributeSetterFastCallback(Local<Object> receiver, int32_t value,
1360 FastApiCallbackOptions& options) {
1361 FastCApiObject* self = UnwrapObject(receiver);
1363 self->fast_call_count_++;
1364 self->attribute_value_ = value;
1365 }
1366
1367#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1368 static void AttributeSetterFastCallbackPatch(AnyCType receiver,
1369 AnyCType value,
1370 AnyCType options) {
1371 AttributeSetterFastCallback(receiver.object_value, value.int32_value,
1372 *options.options_value);
1373 }
1374#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1375
1376 static void FastCallCount(const FunctionCallbackInfo<Value>& info) {
1377 FastCApiObject* self = UnwrapObject(info.This());
1379 info.GetReturnValue().Set(
1380 Number::New(info.GetIsolate(), self->fast_call_count()));
1381 }
1382 static void SlowCallCount(const FunctionCallbackInfo<Value>& info) {
1384 FastCApiObject* self = UnwrapObject(info.This());
1386 info.GetReturnValue().Set(
1387 Number::New(info.GetIsolate(), self->slow_call_count()));
1388 }
1389 static void ResetCounts(const FunctionCallbackInfo<Value>& info) {
1391 FastCApiObject* self = UnwrapObject(info.This());
1393 self->reset_counts();
1394 info.GetReturnValue().Set(Undefined(info.GetIsolate()));
1395 }
1396 static void SupportsFPParams(const FunctionCallbackInfo<Value>& info) {
1398 FastCApiObject* self = UnwrapObject(info.This());
1400 info.GetReturnValue().Set(self->supports_fp_params_);
1401 }
1402
1403 int fast_call_count() const { return fast_call_count_; }
1404 int slow_call_count() const { return slow_call_count_; }
1405 void reset_counts() {
1406 fast_call_count_ = 0;
1407 slow_call_count_ = 0;
1408 }
1409
1410 static const int kV8WrapperObjectIndex = 1;
1411
1412 private:
1413 static bool IsValidApiObject(Local<Object> object) {
1414 if (object->IsInt32()) return false;
1415 auto instance_type = i::Internals::GetInstanceType(
1417 return (base::IsInRange(instance_type, i::Internals::kFirstJSApiObjectType,
1418 i::Internals::kLastJSApiObjectType) ||
1419 instance_type == i::Internals::kJSSpecialApiObjectType);
1420 }
1421 static FastCApiObject* UnwrapObject(Local<Object> object) {
1422 if (!IsValidApiObject(object)) {
1423 return nullptr;
1424 }
1425 if (object->InternalFieldCount() <= kV8WrapperObjectIndex) {
1426 return nullptr;
1427 }
1428 FastCApiObject* wrapped = reinterpret_cast<FastCApiObject*>(
1429 object->GetAlignedPointerFromInternalField(kV8WrapperObjectIndex));
1430 CHECK_NOT_NULL(wrapped);
1431 return wrapped;
1432 }
1433
1434 int fast_call_count_ = 0, slow_call_count_ = 0;
1435 int attribute_value_ = 0;
1436#ifdef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
1437 bool supports_fp_params_ = true;
1438#else // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
1439 bool supports_fp_params_ = false;
1440#endif // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
1441};
1442
1443#undef CHECK_SELF_OR_THROW_SLOW
1444#undef CHECK_SELF_OR_THROW_FAST
1445#undef CHECK_SELF_OR_THROW_FAST_OPTIONS
1446
1447// The object is statically initialized for simplicity, typically the embedder
1448// will take care of managing their C++ objects lifetime.
1449thread_local FastCApiObject kFastCApiObject;
1450} // namespace
1451
1452// static
1453FastCApiObject& FastCApiObject::instance() { return kFastCApiObject; }
1454
1457 if (!info.IsConstructCall()) {
1458 info.GetIsolate()->ThrowError(
1459 "FastCAPI helper must be constructed with new.");
1460 return;
1461 }
1462 Local<Object> api_object = info.This();
1463 api_object->SetAlignedPointerInInternalField(
1464 FastCApiObject::kV8WrapperObjectIndex,
1465 reinterpret_cast<void*>(&kFastCApiObject));
1466 api_object->SetAccessorProperty(
1467 String::NewFromUtf8Literal(info.GetIsolate(), "supports_fp_params"),
1468 FunctionTemplate::New(info.GetIsolate(), FastCApiObject::SupportsFPParams)
1469 ->GetFunction(api_object->GetCreationContext(info.GetIsolate())
1470 .ToLocalChecked())
1471 .ToLocalChecked());
1472}
1473
1475 Local<FunctionTemplate> api_obj_ctor =
1477 PerIsolateData::Get(isolate)->SetTestApiObjectCtor(api_obj_ctor);
1478 Local<Signature> signature = Signature::New(isolate, api_obj_ctor);
1479 {
1480 CFunction throw_no_fallback_func = CFunction::Make(
1481 FastCApiObject::ThrowNoFallbackFastCallback V8_IF_USE_SIMULATOR(
1482 FastCApiObject::ThrowNoFallbackFastCallbackPatch));
1483 api_obj_ctor->PrototypeTemplate()->Set(
1484 isolate, "throw_no_fallback",
1486 isolate, FastCApiObject::ThrowFallbackSlowCallback, Local<Value>(),
1488 SideEffectType::kHasSideEffect, &throw_no_fallback_func));
1489
1490 CFunction copy_str_func = CFunction::Make(
1491 FastCApiObject::CopyStringFastCallback V8_IF_USE_SIMULATOR(
1492 FastCApiObject::CopyStringFastCallbackPatch));
1493 api_obj_ctor->PrototypeTemplate()->Set(
1494 isolate, "copy_string",
1495 FunctionTemplate::New(isolate, FastCApiObject::CopyStringSlowCallback,
1496 Local<Value>(), signature, 1,
1498 SideEffectType::kHasSideEffect, &copy_str_func));
1499
1500 CFunction add_all_c_func =
1501 CFunction::Make(FastCApiObject::AddAllFastCallback V8_IF_USE_SIMULATOR(
1502 FastCApiObject::AddAllFastCallbackPatch));
1503 api_obj_ctor->PrototypeTemplate()->Set(
1504 isolate, "add_all",
1505 FunctionTemplate::New(isolate, FastCApiObject::AddAllSlowCallback,
1506 Local<Value>(), signature, 1,
1508 SideEffectType::kHasSideEffect, &add_all_c_func));
1509
1510 CFunction fast_setter = CFunction::Make(
1511 FastCApiObject::AttributeSetterFastCallback V8_IF_USE_SIMULATOR(
1512 FastCApiObject::AttributeSetterFastCallback));
1513 CFunction fast_getter = CFunction::Make(
1514 FastCApiObject::AttributeGetterFastCallback V8_IF_USE_SIMULATOR(
1515 FastCApiObject::AttributeGetterFastCallback));
1516
1517 api_obj_ctor->PrototypeTemplate()->SetAccessorProperty(
1518 String::NewFromUtf8(isolate, "fast_attribute").ToLocalChecked(),
1520 isolate, FastCApiObject::AttributeGetterSlowCallback,
1522 SideEffectType::kHasSideEffect, &fast_getter),
1524 isolate, FastCApiObject::AttributeSetterSlowCallback,
1526 SideEffectType::kHasSideEffect, &fast_setter),
1528
1529 CFunction add_all_seq_c_func = CFunction::Make(
1530 FastCApiObject::AddAllSequenceFastCallback V8_IF_USE_SIMULATOR(
1531 FastCApiObject::AddAllSequenceFastCallbackPatch));
1532 api_obj_ctor->PrototypeTemplate()->Set(
1533 isolate, "add_all_sequence",
1535 isolate, FastCApiObject::AddAllSequenceSlowCallback, Local<Value>(),
1536 signature, 1, ConstructorBehavior::kThrow,
1537 SideEffectType::kHasSideEffect, &add_all_seq_c_func));
1538
1539 CFunction add_all_uint8_typed_array_c_func = CFunction::Make(
1540 FastCApiObject::AddAllTypedArrayFastCallback<uint8_t>
1542 FastCApiObject::AddAllTypedArrayFastCallbackPatch<uint8_t>));
1543
1544 api_obj_ctor->PrototypeTemplate()->Set(
1545 isolate, "add_all_uint8_typed_array",
1547 isolate, FastCApiObject::AddAllTypedArraySlowCallback,
1549 SideEffectType::kHasSideEffect, &add_all_uint8_typed_array_c_func));
1550
1551 CFunction add_all_int32_typed_array_c_func = CFunction::Make(
1552 FastCApiObject::AddAllTypedArrayFastCallback<int32_t>
1554 FastCApiObject::AddAllTypedArrayFastCallbackPatch<int32_t>));
1555
1556 api_obj_ctor->PrototypeTemplate()->Set(
1557 isolate, "add_all_int32_typed_array",
1559 isolate, FastCApiObject::AddAllTypedArraySlowCallback,
1561 SideEffectType::kHasSideEffect, &add_all_int32_typed_array_c_func));
1562
1563 CFunction add_all_int64_typed_array_c_func = CFunction::Make(
1564 FastCApiObject::AddAllTypedArrayFastCallback<int64_t>
1566 FastCApiObject::AddAllTypedArrayFastCallbackPatch<int64_t>));
1567 api_obj_ctor->PrototypeTemplate()->Set(
1568 isolate, "add_all_int64_typed_array",
1570 isolate, FastCApiObject::AddAllTypedArraySlowCallback,
1572 SideEffectType::kHasSideEffect, &add_all_int64_typed_array_c_func));
1573
1574 CFunction add_all_uint64_typed_array_c_func = CFunction::Make(
1575 FastCApiObject::AddAllTypedArrayFastCallback<uint64_t>
1577 FastCApiObject::AddAllTypedArrayFastCallbackPatch<uint64_t>));
1578 api_obj_ctor->PrototypeTemplate()->Set(
1579 isolate, "add_all_uint64_typed_array",
1581 isolate, FastCApiObject::AddAllTypedArraySlowCallback,
1584 &add_all_uint64_typed_array_c_func));
1585
1586 CFunction add_all_uint32_typed_array_c_func = CFunction::Make(
1587 FastCApiObject::AddAllTypedArrayFastCallback<uint32_t>
1589 FastCApiObject::AddAllTypedArrayFastCallbackPatch<uint32_t>));
1590 api_obj_ctor->PrototypeTemplate()->Set(
1591 isolate, "add_all_uint32_typed_array",
1593 isolate, FastCApiObject::AddAllTypedArraySlowCallback,
1596 &add_all_uint32_typed_array_c_func));
1597
1598 CFunction add_all_float32_typed_array_c_func = CFunction::Make(
1599 FastCApiObject::AddAllTypedArrayFastCallback<float> V8_IF_USE_SIMULATOR(
1600 FastCApiObject::AddAllTypedArrayFastCallbackPatch<float>));
1601 api_obj_ctor->PrototypeTemplate()->Set(
1602 isolate, "add_all_float32_typed_array",
1604 isolate, FastCApiObject::AddAllTypedArraySlowCallback,
1607 &add_all_float32_typed_array_c_func));
1608
1609 CFunction add_all_no_options_c_func = CFunction::Make(
1610 FastCApiObject::AddAllFastCallbackNoOptions V8_IF_USE_SIMULATOR(
1611 FastCApiObject::AddAllFastCallbackNoOptionsPatch),
1613 api_obj_ctor->PrototypeTemplate()->Set(
1614 isolate, "add_all_no_options",
1616 isolate, FastCApiObject::AddAllSlowCallback, Local<Value>(),
1618 SideEffectType::kHasSideEffect, &add_all_no_options_c_func));
1619
1620 CFunction add_all_float64_typed_array_c_func = CFunction::Make(
1621 FastCApiObject::AddAllTypedArrayFastCallback<double>
1623 FastCApiObject::AddAllTypedArrayFastCallbackPatch<double>));
1624 api_obj_ctor->PrototypeTemplate()->Set(
1625 isolate, "add_all_float64_typed_array",
1627 isolate, FastCApiObject::AddAllTypedArraySlowCallback,
1630 &add_all_float64_typed_array_c_func));
1631
1632 const CFunction add_all_overloads[] = {
1633 add_all_seq_c_func,
1634 add_all_no_options_c_func,
1635 };
1636 api_obj_ctor->PrototypeTemplate()->Set(
1637 isolate, "add_all_overload",
1639 isolate, FastCApiObject::AddAllSequenceSlowCallback, Local<Value>(),
1640 signature, 1, ConstructorBehavior::kThrow,
1641 SideEffectType::kHasSideEffect, {add_all_overloads, 2}));
1642
1643 CFunction add_all_32bit_int_8args_c_func = CFunction::Make(
1644 FastCApiObject::AddAll32BitIntFastCallback_8Args V8_IF_USE_SIMULATOR(
1645 FastCApiObject::AddAll32BitIntFastCallback_8ArgsPatch));
1646 CFunction add_all_32bit_int_6args_c_func = CFunction::Make(
1647 FastCApiObject::AddAll32BitIntFastCallback_6Args V8_IF_USE_SIMULATOR(
1648 FastCApiObject::AddAll32BitIntFastCallback_6ArgsPatch));
1649 CFunction add_all_32bit_int_5args_c_func = CFunction::Make(
1650 FastCApiObject::AddAll32BitIntFastCallback_5Args V8_IF_USE_SIMULATOR(
1651 FastCApiObject::AddAll32BitIntFastCallback_5ArgsPatch));
1652 const CFunction c_function_overloads[] = {add_all_32bit_int_6args_c_func,
1653 add_all_32bit_int_5args_c_func};
1654
1655 api_obj_ctor->PrototypeTemplate()->Set(
1656 isolate, "overloaded_add_all_32bit_int",
1658 isolate, FastCApiObject::AddAll32BitIntSlowCallback, Local<Value>(),
1659 signature, 1, ConstructorBehavior::kThrow,
1660 SideEffectType::kHasSideEffect, {c_function_overloads, 2}));
1661
1662 api_obj_ctor->PrototypeTemplate()->Set(
1663 isolate, "overloaded_add_all_8args",
1665 isolate, FastCApiObject::AddAll32BitIntSlowCallback, Local<Value>(),
1666 signature, 1, ConstructorBehavior::kThrow,
1667 SideEffectType::kHasSideEffect, &add_all_32bit_int_8args_c_func));
1668
1669 api_obj_ctor->PrototypeTemplate()->Set(
1670 isolate, "overloaded_add_all_32bit_int_no_sig",
1672 isolate, FastCApiObject::AddAll32BitIntSlowCallback, Local<Value>(),
1674 SideEffectType::kHasSideEffect, {c_function_overloads, 2}));
1675
1676 CFunction add_32bit_int_c_func = CFunction::Make(
1677 FastCApiObject::Add32BitIntFastCallback V8_IF_USE_SIMULATOR(
1678 FastCApiObject::Add32BitIntFastCallbackPatch));
1679 api_obj_ctor->PrototypeTemplate()->Set(
1680 isolate, "add_32bit_int",
1682 isolate, FastCApiObject::Add32BitIntSlowCallback, Local<Value>(),
1683 signature, 1, ConstructorBehavior::kThrow,
1684 SideEffectType::kHasSideEffect, &add_32bit_int_c_func));
1685
1686 CFunction add_all_annotate_c_func = CFunction::Make(
1687 FastCApiObject::AddAllAnnotateFastCallback<
1689 V8_IF_USE_SIMULATOR(FastCApiObject::AddAllAnnotateFastCallbackPatch<
1691 api_obj_ctor->PrototypeTemplate()->Set(
1692 isolate, "add_all_annotate_enforce_range",
1694 isolate, FastCApiObject::AddAllAnnotateSlowCallback, Local<Value>(),
1695 signature, 1, ConstructorBehavior::kThrow,
1696 SideEffectType::kHasSideEffect, &add_all_annotate_c_func));
1697
1698 // Testing enforce range annotation.
1699
1700 CFunction enforce_range_compare_i32_c_func =
1702 .Fn(FastCApiObject::EnforceRangeCompare<int32_t>)
1704#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1705 .Patch(FastCApiObject::EnforceRangeCompareI32Patch)
1706#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1707 .Build();
1708 api_obj_ctor->PrototypeTemplate()->Set(
1709 isolate, "enforce_range_compare_i32",
1711 isolate, FastCApiObject::EnforceRangeCompareSlowCallback<int32_t>,
1713 SideEffectType::kHasSideEffect, &enforce_range_compare_i32_c_func));
1714
1715 CFunction enforce_range_compare_u32_c_func =
1717 .Fn(FastCApiObject::EnforceRangeCompare<uint32_t>)
1719#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1720 .Patch(FastCApiObject::EnforceRangeCompareU32Patch)
1721#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1722 .Build();
1723 api_obj_ctor->PrototypeTemplate()->Set(
1724 isolate, "enforce_range_compare_u32",
1726 isolate, FastCApiObject::EnforceRangeCompareSlowCallback<uint32_t>,
1728 SideEffectType::kHasSideEffect, &enforce_range_compare_u32_c_func));
1729
1730 CFunction enforce_range_compare_i64_c_func =
1732 .Fn(FastCApiObject::EnforceRangeCompare<int64_t>)
1734#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1735 .Patch(FastCApiObject::EnforceRangeCompareI64Patch)
1736#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1737 .Build();
1738 api_obj_ctor->PrototypeTemplate()->Set(
1739 isolate, "enforce_range_compare_i64",
1741 isolate, FastCApiObject::EnforceRangeCompareSlowCallback<int64_t>,
1743 SideEffectType::kHasSideEffect, &enforce_range_compare_i64_c_func));
1744
1745 CFunction enforce_range_compare_u64_c_func =
1747 .Fn(FastCApiObject::EnforceRangeCompare<uint64_t>)
1749#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1750 .Patch(FastCApiObject::EnforceRangeCompareU64Patch)
1751#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1752 .Build();
1753 api_obj_ctor->PrototypeTemplate()->Set(
1754 isolate, "enforce_range_compare_u64",
1756 isolate, FastCApiObject::EnforceRangeCompareSlowCallback<uint64_t>,
1758 SideEffectType::kHasSideEffect, &enforce_range_compare_u64_c_func));
1759
1760 // Testing clamp annotation.
1761
1762 CFunction clamp_compare_i32_c_func =
1764 .Fn(FastCApiObject::ClampCompare<int32_t>)
1766#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1767 .Patch(FastCApiObject::ClampCompareI32Patch)
1768#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1769 .Build();
1770 api_obj_ctor->PrototypeTemplate()->Set(
1771 isolate, "clamp_compare_i32",
1773 isolate, FastCApiObject::ClampCompareSlowCallback<int32_t>,
1775 SideEffectType::kHasSideEffect, &clamp_compare_i32_c_func));
1776
1777 CFunction clamp_compare_u32_c_func =
1779 .Fn(FastCApiObject::ClampCompare<uint32_t>)
1781#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1782 .Patch(FastCApiObject::ClampCompareU32Patch)
1783#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1784 .Build();
1785 api_obj_ctor->PrototypeTemplate()->Set(
1786 isolate, "clamp_compare_u32",
1788 isolate, FastCApiObject::ClampCompareSlowCallback<uint32_t>,
1790 SideEffectType::kHasSideEffect, &clamp_compare_u32_c_func));
1791
1792 CFunction clamp_compare_i64_c_func =
1794 .Fn(FastCApiObject::ClampCompare<int64_t>)
1796#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1797 .Patch(FastCApiObject::ClampCompareI64Patch)
1798#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1799 .Build();
1800 api_obj_ctor->PrototypeTemplate()->Set(
1801 isolate, "clamp_compare_i64",
1803 isolate, FastCApiObject::ClampCompareSlowCallback<int64_t>,
1805 SideEffectType::kHasSideEffect, &clamp_compare_i64_c_func));
1806
1807 CFunction clamp_compare_u64_c_func =
1809 .Fn(FastCApiObject::ClampCompare<uint64_t>)
1811#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1812 .Patch(FastCApiObject::ClampCompareU64Patch)
1813#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1814 .Build();
1815 api_obj_ctor->PrototypeTemplate()->Set(
1816 isolate, "clamp_compare_u64",
1818 isolate, FastCApiObject::ClampCompareSlowCallback<uint64_t>,
1820 SideEffectType::kHasSideEffect, &clamp_compare_u64_c_func));
1821
1822 CFunction is_valid_api_object_c_func =
1823 CFunction::Make(FastCApiObject::IsFastCApiObjectFastCallback);
1824 api_obj_ctor->PrototypeTemplate()->Set(
1825 isolate, "is_fast_c_api_object",
1827 isolate, FastCApiObject::IsFastCApiObjectSlowCallback,
1829 SideEffectType::kHasSideEffect, &is_valid_api_object_c_func));
1830
1831 CFunction test_wasm_memory_c_func =
1832 CFunction::Make(FastCApiObject::TestWasmMemoryFastCallback);
1833 api_obj_ctor->PrototypeTemplate()->Set(
1834 isolate, "test_wasm_memory",
1836 isolate, FastCApiObject::TestWasmMemorySlowCallback, Local<Value>(),
1838 SideEffectType::kHasSideEffect, &test_wasm_memory_c_func));
1839
1840 api_obj_ctor->PrototypeTemplate()->Set(
1841 isolate, "assert_is_external",
1842 FunctionTemplate::New(isolate, FastCApiObject::AssertIsExternal,
1843 Local<Value>(), signature, 1,
1846
1847 CFunction get_pointer_c_func =
1848 CFunction::Make(FastCApiObject::GetPointerFastCallback);
1849 api_obj_ctor->PrototypeTemplate()->Set(
1850 isolate, "get_pointer",
1852 isolate, FastCApiObject::GetPointerSlowCallback, Local<Value>(),
1853 signature, 1, ConstructorBehavior::kThrow,
1854 SideEffectType::kHasSideEffect, &get_pointer_c_func));
1855 CFunction get_null_pointer_c_func =
1856 CFunction::Make(FastCApiObject::GetNullPointerFastCallback);
1857 api_obj_ctor->PrototypeTemplate()->Set(
1858 isolate, "get_null_pointer",
1860 isolate, FastCApiObject::GetNullPointerSlowCallback, Local<Value>(),
1861 signature, 1, ConstructorBehavior::kThrow,
1862 SideEffectType::kHasSideEffect, &get_null_pointer_c_func));
1863 CFunction pass_pointer_c_func =
1864 CFunction::Make(FastCApiObject::PassPointerFastCallback);
1865 api_obj_ctor->PrototypeTemplate()->Set(
1866 isolate, "pass_pointer",
1868 isolate, FastCApiObject::PassPointerSlowCallback, Local<Value>(),
1869 signature, 1, ConstructorBehavior::kThrow,
1870 SideEffectType::kHasSideEffect, &pass_pointer_c_func));
1871 CFunction compare_pointers_c_func =
1872 CFunction::Make(FastCApiObject::ComparePointersFastCallback);
1873 api_obj_ctor->PrototypeTemplate()->Set(
1874 isolate, "compare_pointers",
1876 isolate, FastCApiObject::ComparePointersSlowCallback,
1878 SideEffectType::kHasSideEffect, &compare_pointers_c_func));
1879 CFunction sum_int64_as_number_c_func =
1880 CFunctionBuilder().Fn(FastCApiObject::sumInt64FastCallback).Build();
1881 api_obj_ctor->PrototypeTemplate()->Set(
1882 isolate, "sum_int64_as_number",
1884 isolate, FastCApiObject::sumInt64AsNumberSlowCallback,
1886 SideEffectType::kHasSideEffect, &sum_int64_as_number_c_func));
1887 CFunction sum_int64_as_bigint_c_func =
1889 .Fn(FastCApiObject::sumInt64FastCallback)
1891 api_obj_ctor->PrototypeTemplate()->Set(
1892 isolate, "sum_int64_as_bigint",
1894 isolate, FastCApiObject::sumInt64AsBigIntSlowCallback,
1896 SideEffectType::kHasSideEffect, &sum_int64_as_bigint_c_func));
1897 CFunction sum_uint64_as_number_c_func =
1898 CFunctionBuilder().Fn(FastCApiObject::sumUint64FastCallback).Build();
1899 api_obj_ctor->PrototypeTemplate()->Set(
1900 isolate, "sum_uint64_as_number",
1902 isolate, FastCApiObject::sumUint64AsNumberSlowCallback,
1904 SideEffectType::kHasSideEffect, &sum_uint64_as_number_c_func));
1905 CFunction sum_uint64_as_bigint_c_func =
1907 .Fn(FastCApiObject::sumUint64FastCallback)
1909 api_obj_ctor->PrototypeTemplate()->Set(
1910 isolate, "sum_uint64_as_bigint",
1912 isolate, FastCApiObject::sumUint64AsBigIntSlowCallback,
1914 SideEffectType::kHasSideEffect, &sum_uint64_as_bigint_c_func));
1915
1916 api_obj_ctor->PrototypeTemplate()->Set(
1917 isolate, "fast_call_count",
1919 isolate, FastCApiObject::FastCallCount, Local<Value>(), signature,
1921 api_obj_ctor->PrototypeTemplate()->Set(
1922 isolate, "slow_call_count",
1924 isolate, FastCApiObject::SlowCallCount, Local<Value>(), signature,
1926 api_obj_ctor->PrototypeTemplate()->Set(
1927 isolate, "reset_counts",
1928 FunctionTemplate::New(isolate, FastCApiObject::ResetCounts,
1929 Local<Value>(), signature, 1,
1931
1932 CFunction add_all_32bit_int_5args_enforce_range_c_func =
1934 .Fn(FastCApiObject::AddAll32BitIntFastCallback_5Args)
1936 .Arg<5, v8::CTypeInfo::Flags::kEnforceRangeBit>()
1937#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1938 .Patch(FastCApiObject::AddAll32BitIntFastCallback_5ArgsPatch)
1939#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
1940 .Build();
1941 api_obj_ctor->PrototypeTemplate()->Set(
1942 isolate, "add_all_5args_enforce_range",
1944 isolate, FastCApiObject::AddAll32BitIntSlowCallback, Local<Value>(),
1945 signature, 1, ConstructorBehavior::kThrow,
1947 &add_all_32bit_int_5args_enforce_range_c_func));
1948 }
1949 api_obj_ctor->InstanceTemplate()->SetInternalFieldCount(
1950 FastCApiObject::kV8WrapperObjectIndex + 1);
1951
1952 return api_obj_ctor;
1953}
1954
1956 if (!info.IsConstructCall()) {
1957 info.GetIsolate()->ThrowError(
1958 "LeafInterfaceType helper must be constructed with new.");
1959 }
1960}
1961
1963 Isolate* isolate) {
1964 Local<FunctionTemplate> leaf_object_ctor =
1966 leaf_object_ctor->SetClassName(
1967 String::NewFromUtf8Literal(isolate, "LeafInterfaceType"));
1968 return leaf_object_ctor;
1969}
1970
1971} // namespace v8
#define T
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
static Local< BigInt > New(Isolate *isolate, int64_t value)
Definition api.cc:9591
static Local< BigInt > NewFromUnsigned(Isolate *isolate, uint64_t value)
Definition api.cc:9598
static CFunction Make(F *func, CFunctionInfo::Int64Representation int64_rep=CFunctionInfo::Int64Representation::kNumber)
static constexpr CTypeInfo Build()
constexpr Identifier GetId() const
static Local< External > New(Isolate *isolate, void *value)
Definition api.cc:7483
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=nullptr, Local< Value > data=Local< Value >(), Local< Signature > signature=Local< Signature >(), int length=0, ConstructorBehavior behavior=ConstructorBehavior::kAllow, SideEffectType side_effect_type=SideEffectType::kHasSideEffect, const CFunction *c_function=nullptr, uint16_t instance_type=0, uint16_t allowed_receiver_instance_type_range_start=0, uint16_t allowed_receiver_instance_type_range_end=0)
Definition api.cc:1101
static Local< FunctionTemplate > NewWithCFunctionOverloads(Isolate *isolate, FunctionCallback callback=nullptr, Local< Value > data=Local< Value >(), Local< Signature > signature=Local< Signature >(), int length=0, ConstructorBehavior behavior=ConstructorBehavior::kAllow, SideEffectType side_effect_type=SideEffectType::kHasSideEffect, const MemorySpan< const CFunction > &c_function_overloads={})
Definition api.cc:1158
static Local< Integer > NewFromUnsigned(Isolate *isolate, uint32_t value)
Definition api.cc:9579
static Isolate * GetCurrent()
Definition api.cc:9949
V8_INLINE Local< S > As() const
V8_INLINE Local< T > ToLocalChecked()
V8_INLINE bool IsEmpty() const
static Local< Number > New(Isolate *isolate, double value)
Definition api.cc:9557
static PerIsolateData * Get(Isolate *isolate)
Definition d8.h:300
Local< FunctionTemplate > GetTestApiObjectCtor() const
Definition d8.cc:1948
void SetTestApiObjectCtor(Local< FunctionTemplate > ctor)
Definition d8.cc:1952
static Local< FunctionTemplate > CreateLeafInterfaceTypeTemplate(Isolate *isolate)
Definition d8-test.cc:1962
static Local< FunctionTemplate > CreateTestFastCApiTemplate(Isolate *isolate)
Definition d8-test.cc:1474
static Local< Signature > New(Isolate *isolate, Local< FunctionTemplate > receiver=Local< FunctionTemplate >())
Definition api.cc:1204
static V8_WARN_UNUSED_RESULT Local< String > NewFromUtf8Literal(Isolate *isolate, const char(&literal)[N], NewStringType type=NewStringType::kNormal)
static V8_WARN_UNUSED_RESULT MaybeLocal< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=NewStringType::kNormal, int length=-1)
Definition api.cc:7593
constexpr auto Fn(R(*fn)(Args...))
static V8_INLINE Address ValueAsAddress(const T *value)
#define V8_IF_USE_SIMULATOR(V)
Definition globals.h:201
#define CHECK_SELF_OR_THROW_SLOW()
Definition d8-test.cc:34
#define CHECK_SELF_OR_THROW_FAST_OPTIONS(return_value)
Definition d8-test.cc:19
std::optional< TNode< JSArray > > a
TNode< Object > receiver
ZoneVector< RpoNumber > & result
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
Definition bounds.h:20
constexpr double kMaxSafeInteger
Definition globals.h:1985
bool V8_EXPORT ValidateCallbackInfo(const FunctionCallbackInfo< void > &info)
Definition api.cc:12301
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr double kMinSafeInteger
Definition globals.h:1987
@ None
Definition v8-object.h:141
V8_INLINE Local< Primitive > Null(Isolate *isolate)
internal::CFunctionBuilder CFunctionBuilder
V8_INLINE Local< Primitive > Undefined(Isolate *isolate)
void CreateLeafInterfaceObject(const FunctionCallbackInfo< Value > &info)
Definition d8-test.cc:1955
void CreateFastCAPIObject(const FunctionCallbackInfo< Value > &info)
Definition d8-test.cc:1455
bool V8_EXPORT TryToCopyAndConvertArrayToCppBuffer(Local< Array > src, T *dst, uint32_t max_length)
Definition api-inl.h:337
#define FATAL(...)
Definition logging.h:47
#define CHECK(condition)
Definition logging.h:124
#define CHECK_GT(lhs, rhs)
#define CHECK_LE(lhs, rhs)
#define CHECK_NOT_NULL(val)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
std::unique_ptr< ValueMirror > value