1// Copyright 2018 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/external-reference.h"
6
7#include "src/api.h"
8#include "src/base/ieee754.h"
9#include "src/compiler/code-assembler.h"
10#include "src/counters.h"
11#include "src/cpu-features.h"
12#include "src/date.h"
13#include "src/debug/debug.h"
14#include "src/deoptimizer.h"
15#include "src/elements.h"
16#include "src/hash-seed-inl.h"
17#include "src/heap/heap.h"
18#include "src/objects/ordered-hash-table.h"
19// For IncrementalMarking::RecordWriteFromCode. TODO(jkummerow): Drop.
20#include "src/heap/heap-inl.h"
21#include "src/ic/stub-cache.h"
22#include "src/interpreter/interpreter.h"
23#include "src/isolate.h"
24#include "src/log.h"
25#include "src/math-random.h"
26#include "src/microtask-queue.h"
27#include "src/objects-inl.h"
28#include "src/regexp/regexp-stack.h"
29#include "src/simulator-base.h"
30#include "src/string-search.h"
31#include "src/wasm/wasm-external-refs.h"
32
33// Include native regexp-macro-assembler.
34#if V8_TARGET_ARCH_IA32
35#include "src/regexp/ia32/regexp-macro-assembler-ia32.h" // NOLINT
36#elif V8_TARGET_ARCH_X64
37#include "src/regexp/x64/regexp-macro-assembler-x64.h" // NOLINT
38#elif V8_TARGET_ARCH_ARM64
39#include "src/regexp/arm64/regexp-macro-assembler-arm64.h" // NOLINT
40#elif V8_TARGET_ARCH_ARM
41#include "src/regexp/arm/regexp-macro-assembler-arm.h" // NOLINT
42#elif V8_TARGET_ARCH_PPC
43#include "src/regexp/ppc/regexp-macro-assembler-ppc.h" // NOLINT
44#elif V8_TARGET_ARCH_MIPS
45#include "src/regexp/mips/regexp-macro-assembler-mips.h" // NOLINT
46#elif V8_TARGET_ARCH_MIPS64
47#include "src/regexp/mips64/regexp-macro-assembler-mips64.h" // NOLINT
48#elif V8_TARGET_ARCH_S390
49#include "src/regexp/s390/regexp-macro-assembler-s390.h" // NOLINT
50#else // Unknown architecture.
51#error "Unknown architecture."
52#endif // Target architecture.
53
54#ifdef V8_INTL_SUPPORT
55#include "src/objects/intl-objects.h"
56#endif // V8_INTL_SUPPORT
57
58namespace v8 {
59namespace internal {
60
61// -----------------------------------------------------------------------------
62// Common double constants.
63
64constexpr double double_min_int_constant = kMinInt;
65constexpr double double_one_half_constant = 0.5;
66constexpr uint64_t double_the_hole_nan_constant = kHoleNanInt64;
67constexpr double double_uint32_bias_constant =
68 static_cast<double>(kMaxUInt32) + 1;
69
70constexpr struct alignas(16) {
71 uint32_t a;
72 uint32_t b;
73 uint32_t c;
74 uint32_t d;
75} float_absolute_constant = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
76
77constexpr struct alignas(16) {
78 uint32_t a;
79 uint32_t b;
80 uint32_t c;
81 uint32_t d;
82} float_negate_constant = {0x80000000, 0x80000000, 0x80000000, 0x80000000};
83
84constexpr struct alignas(16) {
85 uint64_t a;
86 uint64_t b;
87} double_absolute_constant = {uint64_t{0x7FFFFFFFFFFFFFFF},
88 uint64_t{0x7FFFFFFFFFFFFFFF}};
89
90constexpr struct alignas(16) {
91 uint64_t a;
92 uint64_t b;
93} double_negate_constant = {uint64_t{0x8000000000000000},
94 uint64_t{0x8000000000000000}};
95
96// Implementation of ExternalReference
97
98static ExternalReference::Type BuiltinCallTypeForResultSize(int result_size) {
99 switch (result_size) {
100 case 1:
101 return ExternalReference::BUILTIN_CALL;
102 case 2:
103 return ExternalReference::BUILTIN_CALL_PAIR;
104 }
105 UNREACHABLE();
106}
107
108// static
109ExternalReference ExternalReference::Create(
110 ApiFunction* fun, Type type = ExternalReference::BUILTIN_CALL) {
111 return ExternalReference(Redirect(fun->address(), type));
112}
113
114// static
115ExternalReference ExternalReference::Create(Runtime::FunctionId id) {
116 return Create(Runtime::FunctionForId(id));
117}
118
119// static
120ExternalReference ExternalReference::Create(const Runtime::Function* f) {
121 return ExternalReference(
122 Redirect(f->entry, BuiltinCallTypeForResultSize(f->result_size)));
123}
124
125// static
126ExternalReference ExternalReference::Create(Address address) {
127 return ExternalReference(Redirect(address));
128}
129
130ExternalReference ExternalReference::isolate_address(Isolate* isolate) {
131 return ExternalReference(isolate);
132}
133
134ExternalReference ExternalReference::builtins_address(Isolate* isolate) {
135 return ExternalReference(isolate->heap()->builtin_address(0));
136}
137
138ExternalReference ExternalReference::handle_scope_implementer_address(
139 Isolate* isolate) {
140 return ExternalReference(isolate->handle_scope_implementer_address());
141}
142
143ExternalReference ExternalReference::interpreter_dispatch_table_address(
144 Isolate* isolate) {
145 return ExternalReference(isolate->interpreter()->dispatch_table_address());
146}
147
148ExternalReference ExternalReference::interpreter_dispatch_counters(
149 Isolate* isolate) {
150 return ExternalReference(
151 isolate->interpreter()->bytecode_dispatch_counters_table());
152}
153
154ExternalReference
155ExternalReference::address_of_interpreter_entry_trampoline_instruction_start(
156 Isolate* isolate) {
157 return ExternalReference(
158 isolate->interpreter()
159 ->address_of_interpreter_entry_trampoline_instruction_start());
160}
161
162ExternalReference ExternalReference::bytecode_size_table_address() {
163 return ExternalReference(
164 interpreter::Bytecodes::bytecode_size_table_address());
165}
166
167// static
168ExternalReference ExternalReference::Create(StatsCounter* counter) {
169 return ExternalReference(
170 reinterpret_cast<Address>(counter->GetInternalPointer()));
171}
172
173// static
174ExternalReference ExternalReference::Create(IsolateAddressId id,
175 Isolate* isolate) {
176 return ExternalReference(isolate->get_address_from_id(id));
177}
178
179// static
180ExternalReference ExternalReference::Create(const SCTableReference& table_ref) {
181 return ExternalReference(table_ref.address());
182}
183
184namespace {
185
186// Helper function to verify that all types in a list of types are scalar.
187// This includes primitive types (int, Address) and pointer types. We also
188// allow void.
189template <typename T>
190constexpr bool AllScalar() {
191 return std::is_scalar<T>::value || std::is_void<T>::value;
192}
193
194template <typename T1, typename T2, typename... Rest>
195constexpr bool AllScalar() {
196 return AllScalar<T1>() && AllScalar<T2, Rest...>();
197}
198
199// Checks a function pointer's type for compatibility with the
200// ExternalReference calling mechanism. Specifically, all arguments
201// as well as the result type must pass the AllScalar check above,
202// because we expect each item to fit into one register or stack slot.
203template <typename T>
204struct IsValidExternalReferenceType;
205
206template <typename Result, typename... Args>
207struct IsValidExternalReferenceType<Result (*)(Args...)> {
208 static const bool value = AllScalar<Result, Args...>();
209};
210
211template <typename Result, typename Class, typename... Args>
212struct IsValidExternalReferenceType<Result (Class::*)(Args...)> {
213 static const bool value = AllScalar<Result, Args...>();
214};
215
216} // namespace
217
218#define FUNCTION_REFERENCE(Name, Target) \
219 ExternalReference ExternalReference::Name() { \
220 STATIC_ASSERT(IsValidExternalReferenceType<decltype(&Target)>::value); \
221 return ExternalReference(Redirect(FUNCTION_ADDR(Target))); \
222 }
223
224#define FUNCTION_REFERENCE_WITH_ISOLATE(Name, Target) \
225 ExternalReference ExternalReference::Name(Isolate* isolate) { \
226 STATIC_ASSERT(IsValidExternalReferenceType<decltype(&Target)>::value); \
227 return ExternalReference(Redirect(FUNCTION_ADDR(Target))); \
228 }
229
230#define FUNCTION_REFERENCE_WITH_TYPE(Name, Target, Type) \
231 ExternalReference ExternalReference::Name() { \
232 STATIC_ASSERT(IsValidExternalReferenceType<decltype(&Target)>::value); \
233 return ExternalReference(Redirect(FUNCTION_ADDR(Target), Type)); \
234 }
235
236FUNCTION_REFERENCE(incremental_marking_record_write_function,
237 IncrementalMarking::RecordWriteFromCode)
238
239ExternalReference ExternalReference::store_buffer_overflow_function() {
240 return ExternalReference(
241 Redirect(Heap::store_buffer_overflow_function_address()));
242}
243
244FUNCTION_REFERENCE(delete_handle_scope_extensions,
245 HandleScope::DeleteExtensions)
246
247FUNCTION_REFERENCE(ephemeron_key_write_barrier_function,
248 Heap::EphemeronKeyWriteBarrierFromCode)
249
250FUNCTION_REFERENCE(get_date_field_function, JSDate::GetField)
251
252ExternalReference ExternalReference::date_cache_stamp(Isolate* isolate) {
253 return ExternalReference(isolate->date_cache()->stamp_address());
254}
255
256// static
257ExternalReference
258ExternalReference::runtime_function_table_address_for_unittests(
259 Isolate* isolate) {
260 return runtime_function_table_address(isolate);
261}
262
263// static
264Address ExternalReference::Redirect(Address address, Type type) {
265#ifdef USE_SIMULATOR
266 return SimulatorBase::RedirectExternalReference(address, type);
267#else
268 return address;
269#endif
270}
271
272ExternalReference ExternalReference::stress_deopt_count(Isolate* isolate) {
273 return ExternalReference(isolate->stress_deopt_count_address());
274}
275
276ExternalReference ExternalReference::force_slow_path(Isolate* isolate) {
277 return ExternalReference(isolate->force_slow_path_address());
278}
279
280FUNCTION_REFERENCE(new_deoptimizer_function, Deoptimizer::New)
281
282FUNCTION_REFERENCE(compute_output_frames_function,
283 Deoptimizer::ComputeOutputFrames)
284
285FUNCTION_REFERENCE(wasm_f32_trunc, wasm::f32_trunc_wrapper)
286FUNCTION_REFERENCE(wasm_f32_floor, wasm::f32_floor_wrapper)
287FUNCTION_REFERENCE(wasm_f32_ceil, wasm::f32_ceil_wrapper)
288FUNCTION_REFERENCE(wasm_f32_nearest_int, wasm::f32_nearest_int_wrapper)
289FUNCTION_REFERENCE(wasm_f64_trunc, wasm::f64_trunc_wrapper)
290FUNCTION_REFERENCE(wasm_f64_floor, wasm::f64_floor_wrapper)
291FUNCTION_REFERENCE(wasm_f64_ceil, wasm::f64_ceil_wrapper)
292FUNCTION_REFERENCE(wasm_f64_nearest_int, wasm::f64_nearest_int_wrapper)
293FUNCTION_REFERENCE(wasm_int64_to_float32, wasm::int64_to_float32_wrapper)
294FUNCTION_REFERENCE(wasm_uint64_to_float32, wasm::uint64_to_float32_wrapper)
295FUNCTION_REFERENCE(wasm_int64_to_float64, wasm::int64_to_float64_wrapper)
296FUNCTION_REFERENCE(wasm_uint64_to_float64, wasm::uint64_to_float64_wrapper)
297FUNCTION_REFERENCE(wasm_float32_to_int64, wasm::float32_to_int64_wrapper)
298FUNCTION_REFERENCE(wasm_float32_to_uint64, wasm::float32_to_uint64_wrapper)
299FUNCTION_REFERENCE(wasm_float64_to_int64, wasm::float64_to_int64_wrapper)
300FUNCTION_REFERENCE(wasm_float64_to_uint64, wasm::float64_to_uint64_wrapper)
301FUNCTION_REFERENCE(wasm_int64_div, wasm::int64_div_wrapper)
302FUNCTION_REFERENCE(wasm_int64_mod, wasm::int64_mod_wrapper)
303FUNCTION_REFERENCE(wasm_uint64_div, wasm::uint64_div_wrapper)
304FUNCTION_REFERENCE(wasm_uint64_mod, wasm::uint64_mod_wrapper)
305FUNCTION_REFERENCE(wasm_word32_ctz, wasm::word32_ctz_wrapper)
306FUNCTION_REFERENCE(wasm_word64_ctz, wasm::word64_ctz_wrapper)
307FUNCTION_REFERENCE(wasm_word32_popcnt, wasm::word32_popcnt_wrapper)
308FUNCTION_REFERENCE(wasm_word64_popcnt, wasm::word64_popcnt_wrapper)
309FUNCTION_REFERENCE(wasm_word32_rol, wasm::word32_rol_wrapper)
310FUNCTION_REFERENCE(wasm_word32_ror, wasm::word32_ror_wrapper)
311FUNCTION_REFERENCE(wasm_memory_copy, wasm::memory_copy_wrapper)
312FUNCTION_REFERENCE(wasm_memory_fill, wasm::memory_fill_wrapper)
313
314static void f64_acos_wrapper(Address data) {
315 double input = ReadUnalignedValue<double>(data);
316 WriteUnalignedValue(data, base::ieee754::acos(input));
317}
318
319FUNCTION_REFERENCE(f64_acos_wrapper_function, f64_acos_wrapper)
320
321static void f64_asin_wrapper(Address data) {
322 double input = ReadUnalignedValue<double>(data);
323 WriteUnalignedValue<double>(data, base::ieee754::asin(input));
324}
325
326FUNCTION_REFERENCE(f64_asin_wrapper_function, f64_asin_wrapper)
327
328FUNCTION_REFERENCE(wasm_float64_pow, wasm::float64_pow_wrapper)
329
330static void f64_mod_wrapper(Address data) {
331 double dividend = ReadUnalignedValue<double>(data);
332 double divisor = ReadUnalignedValue<double>(data + sizeof(dividend));
333 WriteUnalignedValue<double>(data, Modulo(dividend, divisor));
334}
335
336FUNCTION_REFERENCE(f64_mod_wrapper_function, f64_mod_wrapper)
337
338FUNCTION_REFERENCE(wasm_call_trap_callback_for_testing,
339 wasm::call_trap_callback_for_testing)
340
341FUNCTION_REFERENCE(log_enter_external_function, Logger::EnterExternal)
342FUNCTION_REFERENCE(log_leave_external_function, Logger::LeaveExternal)
343
344ExternalReference ExternalReference::isolate_root(Isolate* isolate) {
345 return ExternalReference(isolate->isolate_root());
346}
347
348ExternalReference ExternalReference::allocation_sites_list_address(
349 Isolate* isolate) {
350 return ExternalReference(isolate->heap()->allocation_sites_list_address());
351}
352
353ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
354 return ExternalReference(isolate->stack_guard()->address_of_jslimit());
355}
356
357ExternalReference ExternalReference::address_of_real_stack_limit(
358 Isolate* isolate) {
359 return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
360}
361
362ExternalReference ExternalReference::store_buffer_top(Isolate* isolate) {
363 return ExternalReference(isolate->heap()->store_buffer_top_address());
364}
365
366ExternalReference ExternalReference::heap_is_marking_flag_address(
367 Isolate* isolate) {
368 return ExternalReference(isolate->heap()->IsMarkingFlagAddress());
369}
370
371ExternalReference ExternalReference::new_space_allocation_top_address(
372 Isolate* isolate) {
373 return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
374}
375
376ExternalReference ExternalReference::new_space_allocation_limit_address(
377 Isolate* isolate) {
378 return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
379}
380
381ExternalReference ExternalReference::old_space_allocation_top_address(
382 Isolate* isolate) {
383 return ExternalReference(isolate->heap()->OldSpaceAllocationTopAddress());
384}
385
386ExternalReference ExternalReference::old_space_allocation_limit_address(
387 Isolate* isolate) {
388 return ExternalReference(isolate->heap()->OldSpaceAllocationLimitAddress());
389}
390
391ExternalReference ExternalReference::handle_scope_level_address(
392 Isolate* isolate) {
393 return ExternalReference(HandleScope::current_level_address(isolate));
394}
395
396ExternalReference ExternalReference::handle_scope_next_address(
397 Isolate* isolate) {
398 return ExternalReference(HandleScope::current_next_address(isolate));
399}
400
401ExternalReference ExternalReference::handle_scope_limit_address(
402 Isolate* isolate) {
403 return ExternalReference(HandleScope::current_limit_address(isolate));
404}
405
406ExternalReference ExternalReference::scheduled_exception_address(
407 Isolate* isolate) {
408 return ExternalReference(isolate->scheduled_exception_address());
409}
410
411ExternalReference ExternalReference::address_of_pending_message_obj(
412 Isolate* isolate) {
413 return ExternalReference(isolate->pending_message_obj_address());
414}
415
416FUNCTION_REFERENCE(abort_with_reason, i::abort_with_reason)
417
418ExternalReference
419ExternalReference::address_of_harmony_await_optimization_flag() {
420 return ExternalReference(&FLAG_harmony_await_optimization);
421}
422
423ExternalReference ExternalReference::address_of_min_int() {
424 return ExternalReference(reinterpret_cast<Address>(&double_min_int_constant));
425}
426
427ExternalReference
428ExternalReference::address_of_mock_arraybuffer_allocator_flag() {
429 return ExternalReference(&FLAG_mock_arraybuffer_allocator);
430}
431
432ExternalReference ExternalReference::address_of_runtime_stats_flag() {
433 return ExternalReference(&TracingFlags::runtime_stats);
434}
435
436ExternalReference ExternalReference::address_of_one_half() {
437 return ExternalReference(
438 reinterpret_cast<Address>(&double_one_half_constant));
439}
440
441ExternalReference ExternalReference::address_of_the_hole_nan() {
442 return ExternalReference(
443 reinterpret_cast<Address>(&double_the_hole_nan_constant));
444}
445
446ExternalReference ExternalReference::address_of_uint32_bias() {
447 return ExternalReference(
448 reinterpret_cast<Address>(&double_uint32_bias_constant));
449}
450
451ExternalReference ExternalReference::address_of_float_abs_constant() {
452 return ExternalReference(reinterpret_cast<Address>(&float_absolute_constant));
453}
454
455ExternalReference ExternalReference::address_of_float_neg_constant() {
456 return ExternalReference(reinterpret_cast<Address>(&float_negate_constant));
457}
458
459ExternalReference ExternalReference::address_of_double_abs_constant() {
460 return ExternalReference(
461 reinterpret_cast<Address>(&double_absolute_constant));
462}
463
464ExternalReference ExternalReference::address_of_double_neg_constant() {
465 return ExternalReference(reinterpret_cast<Address>(&double_negate_constant));
466}
467
468ExternalReference ExternalReference::is_profiling_address(Isolate* isolate) {
469 return ExternalReference(isolate->is_profiling_address());
470}
471
472ExternalReference ExternalReference::invoke_function_callback() {
473 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
474 ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL;
475 ApiFunction thunk_fun(thunk_address);
476 return ExternalReference::Create(&thunk_fun, thunk_type);
477}
478
479ExternalReference ExternalReference::invoke_accessor_getter_callback() {
480 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
481 ExternalReference::Type thunk_type = ExternalReference::PROFILING_GETTER_CALL;
482 ApiFunction thunk_fun(thunk_address);
483 return ExternalReference::Create(&thunk_fun, thunk_type);
484}
485
486#if V8_TARGET_ARCH_X64
487#define re_stack_check_func RegExpMacroAssemblerX64::CheckStackGuardState
488#elif V8_TARGET_ARCH_IA32
489#define re_stack_check_func RegExpMacroAssemblerIA32::CheckStackGuardState
490#elif V8_TARGET_ARCH_ARM64
491#define re_stack_check_func RegExpMacroAssemblerARM64::CheckStackGuardState
492#elif V8_TARGET_ARCH_ARM
493#define re_stack_check_func RegExpMacroAssemblerARM::CheckStackGuardState
494#elif V8_TARGET_ARCH_PPC
495#define re_stack_check_func RegExpMacroAssemblerPPC::CheckStackGuardState
496#elif V8_TARGET_ARCH_MIPS
497#define re_stack_check_func RegExpMacroAssemblerMIPS::CheckStackGuardState
498#elif V8_TARGET_ARCH_MIPS64
499#define re_stack_check_func RegExpMacroAssemblerMIPS::CheckStackGuardState
500#elif V8_TARGET_ARCH_S390
501#define re_stack_check_func RegExpMacroAssemblerS390::CheckStackGuardState
502#else
503 UNREACHABLE();
504#endif
505
506FUNCTION_REFERENCE_WITH_ISOLATE(re_check_stack_guard_state, re_stack_check_func)
507#undef re_stack_check_func
508
509FUNCTION_REFERENCE_WITH_ISOLATE(re_grow_stack,
510 NativeRegExpMacroAssembler::GrowStack)
511
512FUNCTION_REFERENCE_WITH_ISOLATE(
513 re_case_insensitive_compare_uc16,
514 NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)
515
516ExternalReference ExternalReference::re_word_character_map(Isolate* isolate) {
517 return ExternalReference(
518 NativeRegExpMacroAssembler::word_character_map_address());
519}
520
521ExternalReference ExternalReference::address_of_static_offsets_vector(
522 Isolate* isolate) {
523 return ExternalReference(
524 reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector()));
525}
526
527ExternalReference ExternalReference::address_of_regexp_stack_limit(
528 Isolate* isolate) {
529 return ExternalReference(isolate->regexp_stack()->limit_address());
530}
531
532ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
533 Isolate* isolate) {
534 return ExternalReference(isolate->regexp_stack()->memory_address());
535}
536
537ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
538 Isolate* isolate) {
539 return ExternalReference(isolate->regexp_stack()->memory_size_address());
540}
541
542FUNCTION_REFERENCE_WITH_TYPE(ieee754_acos_function, base::ieee754::acos,
543 BUILTIN_FP_CALL)
544FUNCTION_REFERENCE_WITH_TYPE(ieee754_acosh_function, base::ieee754::acosh,
545 BUILTIN_FP_FP_CALL)
546FUNCTION_REFERENCE_WITH_TYPE(ieee754_asin_function, base::ieee754::asin,
547 BUILTIN_FP_CALL)
548FUNCTION_REFERENCE_WITH_TYPE(ieee754_asinh_function, base::ieee754::asinh,
549 BUILTIN_FP_FP_CALL)
550FUNCTION_REFERENCE_WITH_TYPE(ieee754_atan_function, base::ieee754::atan,
551 BUILTIN_FP_CALL)
552FUNCTION_REFERENCE_WITH_TYPE(ieee754_atanh_function, base::ieee754::atanh,
553 BUILTIN_FP_FP_CALL)
554FUNCTION_REFERENCE_WITH_TYPE(ieee754_atan2_function, base::ieee754::atan2,
555 BUILTIN_FP_FP_CALL)
556FUNCTION_REFERENCE_WITH_TYPE(ieee754_cbrt_function, base::ieee754::cbrt,
557 BUILTIN_FP_FP_CALL)
558FUNCTION_REFERENCE_WITH_TYPE(ieee754_cos_function, base::ieee754::cos,
559 BUILTIN_FP_CALL)
560FUNCTION_REFERENCE_WITH_TYPE(ieee754_cosh_function, base::ieee754::cosh,
561 BUILTIN_FP_CALL)
562FUNCTION_REFERENCE_WITH_TYPE(ieee754_exp_function, base::ieee754::exp,
563 BUILTIN_FP_CALL)
564FUNCTION_REFERENCE_WITH_TYPE(ieee754_expm1_function, base::ieee754::expm1,
565 BUILTIN_FP_FP_CALL)
566FUNCTION_REFERENCE_WITH_TYPE(ieee754_log_function, base::ieee754::log,
567 BUILTIN_FP_CALL)
568FUNCTION_REFERENCE_WITH_TYPE(ieee754_log1p_function, base::ieee754::log1p,
569 BUILTIN_FP_CALL)
570FUNCTION_REFERENCE_WITH_TYPE(ieee754_log10_function, base::ieee754::log10,
571 BUILTIN_FP_CALL)
572FUNCTION_REFERENCE_WITH_TYPE(ieee754_log2_function, base::ieee754::log2,
573 BUILTIN_FP_CALL)
574FUNCTION_REFERENCE_WITH_TYPE(ieee754_sin_function, base::ieee754::sin,
575 BUILTIN_FP_CALL)
576FUNCTION_REFERENCE_WITH_TYPE(ieee754_sinh_function, base::ieee754::sinh,
577 BUILTIN_FP_CALL)
578FUNCTION_REFERENCE_WITH_TYPE(ieee754_tan_function, base::ieee754::tan,
579 BUILTIN_FP_CALL)
580FUNCTION_REFERENCE_WITH_TYPE(ieee754_tanh_function, base::ieee754::tanh,
581 BUILTIN_FP_CALL)
582FUNCTION_REFERENCE_WITH_TYPE(ieee754_pow_function, base::ieee754::pow,
583 BUILTIN_FP_FP_CALL)
584
585void* libc_memchr(void* string, int character, size_t search_length) {
586 return memchr(string, character, search_length);
587}
588
589FUNCTION_REFERENCE(libc_memchr_function, libc_memchr)
590
591void* libc_memcpy(void* dest, const void* src, size_t n) {
592 return memcpy(dest, src, n);
593}
594
595FUNCTION_REFERENCE(libc_memcpy_function, libc_memcpy)
596
597void* libc_memmove(void* dest, const void* src, size_t n) {
598 return memmove(dest, src, n);
599}
600
601FUNCTION_REFERENCE(libc_memmove_function, libc_memmove)
602
603void* libc_memset(void* dest, int value, size_t n) {
604 DCHECK_EQ(static_cast<byte>(value), value);
605 return memset(dest, value, n);
606}
607
608FUNCTION_REFERENCE(libc_memset_function, libc_memset)
609
610ExternalReference ExternalReference::printf_function() {
611 return ExternalReference(Redirect(FUNCTION_ADDR(std::printf)));
612}
613
614FUNCTION_REFERENCE(refill_math_random, MathRandom::RefillCache)
615
616template <typename SubjectChar, typename PatternChar>
617ExternalReference ExternalReference::search_string_raw() {
618 auto f = SearchStringRaw<SubjectChar, PatternChar>;
619 return ExternalReference(Redirect(FUNCTION_ADDR(f)));
620}
621
622FUNCTION_REFERENCE(jsarray_array_join_concat_to_sequential_string,
623 JSArray::ArrayJoinConcatToSequentialString)
624
625ExternalReference ExternalReference::search_string_raw_one_one() {
626 return search_string_raw<const uint8_t, const uint8_t>();
627}
628
629ExternalReference ExternalReference::search_string_raw_one_two() {
630 return search_string_raw<const uint8_t, const uc16>();
631}
632
633ExternalReference ExternalReference::search_string_raw_two_one() {
634 return search_string_raw<const uc16, const uint8_t>();
635}
636
637ExternalReference ExternalReference::search_string_raw_two_two() {
638 return search_string_raw<const uc16, const uc16>();
639}
640
641FUNCTION_REFERENCE(orderedhashmap_gethash_raw, OrderedHashMap::GetHash)
642
643Address GetOrCreateHash(Isolate* isolate, Address raw_key) {
644 DisallowHeapAllocation no_gc;
645 return Object(raw_key)->GetOrCreateHash(isolate).ptr();
646}
647
648FUNCTION_REFERENCE(get_or_create_hash_raw, GetOrCreateHash)
649
650static Address JSReceiverCreateIdentityHash(Isolate* isolate, Address raw_key) {
651 JSReceiver key = JSReceiver::cast(Object(raw_key));
652 return JSReceiver::CreateIdentityHash(isolate, key).ptr();
653}
654
655FUNCTION_REFERENCE(jsreceiver_create_identity_hash,
656 JSReceiverCreateIdentityHash)
657
658static uint32_t ComputeSeededIntegerHash(Isolate* isolate, uint32_t key) {
659 DisallowHeapAllocation no_gc;
660 return ComputeSeededHash(key, HashSeed(isolate));
661}
662
663FUNCTION_REFERENCE(compute_integer_hash, ComputeSeededIntegerHash)
664FUNCTION_REFERENCE(copy_fast_number_jsarray_elements_to_typed_array,
665 CopyFastNumberJSArrayElementsToTypedArray)
666FUNCTION_REFERENCE(copy_typed_array_elements_to_typed_array,
667 CopyTypedArrayElementsToTypedArray)
668FUNCTION_REFERENCE(copy_typed_array_elements_slice, CopyTypedArrayElementsSlice)
669FUNCTION_REFERENCE(try_internalize_string_function,
670 StringTable::LookupStringIfExists_NoAllocate)
671
672static Address LexicographicCompareWrapper(Isolate* isolate, Address smi_x,
673 Address smi_y) {
674 Smi x(smi_x);
675 Smi y(smi_y);
676 return Smi::LexicographicCompare(isolate, x, y);
677}
678
679FUNCTION_REFERENCE(smi_lexicographic_compare_function,
680 LexicographicCompareWrapper)
681
682FUNCTION_REFERENCE(check_object_type, CheckObjectType)
683
684#ifdef V8_INTL_SUPPORT
685
686static Address ConvertOneByteToLower(Address raw_src, Address raw_dst) {
687 String src = String::cast(Object(raw_src));
688 String dst = String::cast(Object(raw_dst));
689 return Intl::ConvertOneByteToLower(src, dst).ptr();
690}
691FUNCTION_REFERENCE(intl_convert_one_byte_to_lower, ConvertOneByteToLower)
692
693ExternalReference ExternalReference::intl_to_latin1_lower_table() {
694 uint8_t* ptr = const_cast<uint8_t*>(Intl::ToLatin1LowerTable());
695 return ExternalReference(reinterpret_cast<Address>(ptr));
696}
697#endif // V8_INTL_SUPPORT
698
699// Explicit instantiations for all combinations of 1- and 2-byte strings.
700template ExternalReference
701ExternalReference::search_string_raw<const uint8_t, const uint8_t>();
702template ExternalReference
703ExternalReference::search_string_raw<const uint8_t, const uc16>();
704template ExternalReference
705ExternalReference::search_string_raw<const uc16, const uint8_t>();
706template ExternalReference
707ExternalReference::search_string_raw<const uc16, const uc16>();
708
709ExternalReference ExternalReference::FromRawAddress(Address address) {
710 return ExternalReference(address);
711}
712
713ExternalReference ExternalReference::cpu_features() {
714 DCHECK(CpuFeatures::initialized_);
715 return ExternalReference(&CpuFeatures::supported_);
716}
717
718ExternalReference ExternalReference::promise_hook_address(Isolate* isolate) {
719 return ExternalReference(isolate->promise_hook_address());
720}
721
722ExternalReference ExternalReference::async_event_delegate_address(
723 Isolate* isolate) {
724 return ExternalReference(isolate->async_event_delegate_address());
725}
726
727ExternalReference
728ExternalReference::promise_hook_or_async_event_delegate_address(
729 Isolate* isolate) {
730 return ExternalReference(
731 isolate->promise_hook_or_async_event_delegate_address());
732}
733
734ExternalReference ExternalReference::
735 promise_hook_or_debug_is_active_or_async_event_delegate_address(
736 Isolate* isolate) {
737 return ExternalReference(
738 isolate
739 ->promise_hook_or_debug_is_active_or_async_event_delegate_address());
740}
741
742ExternalReference ExternalReference::debug_execution_mode_address(
743 Isolate* isolate) {
744 return ExternalReference(isolate->debug_execution_mode_address());
745}
746
747ExternalReference ExternalReference::debug_is_active_address(Isolate* isolate) {
748 return ExternalReference(isolate->debug()->is_active_address());
749}
750
751ExternalReference ExternalReference::debug_hook_on_function_call_address(
752 Isolate* isolate) {
753 return ExternalReference(isolate->debug()->hook_on_function_call_address());
754}
755
756ExternalReference ExternalReference::runtime_function_table_address(
757 Isolate* isolate) {
758 return ExternalReference(
759 const_cast<Runtime::Function*>(Runtime::RuntimeFunctionTable(isolate)));
760}
761
762static Address InvalidatePrototypeChainsWrapper(Address raw_map) {
763 Map map = Map::cast(Object(raw_map));
764 return JSObject::InvalidatePrototypeChains(map).ptr();
765}
766
767FUNCTION_REFERENCE(invalidate_prototype_chains_function,
768 InvalidatePrototypeChainsWrapper)
769
770double modulo_double_double(double x, double y) { return Modulo(x, y); }
771
772FUNCTION_REFERENCE_WITH_TYPE(mod_two_doubles_operation, modulo_double_double,
773 BUILTIN_FP_FP_CALL)
774
775ExternalReference ExternalReference::debug_suspended_generator_address(
776 Isolate* isolate) {
777 return ExternalReference(isolate->debug()->suspended_generator_address());
778}
779
780ExternalReference ExternalReference::debug_restart_fp_address(
781 Isolate* isolate) {
782 return ExternalReference(isolate->debug()->restart_fp_address());
783}
784
785ExternalReference ExternalReference::fast_c_call_caller_fp_address(
786 Isolate* isolate) {
787 return ExternalReference(
788 isolate->isolate_data()->fast_c_call_caller_fp_address());
789}
790
791ExternalReference ExternalReference::fast_c_call_caller_pc_address(
792 Isolate* isolate) {
793 return ExternalReference(
794 isolate->isolate_data()->fast_c_call_caller_pc_address());
795}
796
797FUNCTION_REFERENCE(call_enqueue_microtask_function,
798 MicrotaskQueue::CallEnqueueMicrotask)
799
800static int64_t atomic_pair_load(intptr_t address) {
801 return std::atomic_load(reinterpret_cast<std::atomic<int64_t>*>(address));
802}
803
804ExternalReference ExternalReference::atomic_pair_load_function() {
805 return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_load)));
806}
807
808static void atomic_pair_store(intptr_t address, int value_low, int value_high) {
809 int64_t value =
810 static_cast<int64_t>(value_high) << 32 | (value_low & 0xFFFFFFFF);
811 std::atomic_store(reinterpret_cast<std::atomic<int64_t>*>(address), value);
812}
813
814ExternalReference ExternalReference::atomic_pair_store_function() {
815 return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_store)));
816}
817
818static int64_t atomic_pair_add(intptr_t address, int value_low,
819 int value_high) {
820 int64_t value =
821 static_cast<int64_t>(value_high) << 32 | (value_low & 0xFFFFFFFF);
822 return std::atomic_fetch_add(reinterpret_cast<std::atomic<int64_t>*>(address),
823 value);
824}
825
826ExternalReference ExternalReference::atomic_pair_add_function() {
827 return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_add)));
828}
829
830static int64_t atomic_pair_sub(intptr_t address, int value_low,
831 int value_high) {
832 int64_t value =
833 static_cast<int64_t>(value_high) << 32 | (value_low & 0xFFFFFFFF);
834 return std::atomic_fetch_sub(reinterpret_cast<std::atomic<int64_t>*>(address),
835 value);
836}
837
838ExternalReference ExternalReference::atomic_pair_sub_function() {
839 return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_sub)));
840}
841
842static int64_t atomic_pair_and(intptr_t address, int value_low,
843 int value_high) {
844 int64_t value =
845 static_cast<int64_t>(value_high) << 32 | (value_low & 0xFFFFFFFF);
846 return std::atomic_fetch_and(reinterpret_cast<std::atomic<int64_t>*>(address),
847 value);
848}
849
850ExternalReference ExternalReference::atomic_pair_and_function() {
851 return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_and)));
852}
853
854static int64_t atomic_pair_or(intptr_t address, int value_low, int value_high) {
855 int64_t value =
856 static_cast<int64_t>(value_high) << 32 | (value_low & 0xFFFFFFFF);
857 return std::atomic_fetch_or(reinterpret_cast<std::atomic<int64_t>*>(address),
858 value);
859}
860
861ExternalReference ExternalReference::atomic_pair_or_function() {
862 return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_or)));
863}
864
865static int64_t atomic_pair_xor(intptr_t address, int value_low,
866 int value_high) {
867 int64_t value =
868 static_cast<int64_t>(value_high) << 32 | (value_low & 0xFFFFFFFF);
869 return std::atomic_fetch_xor(reinterpret_cast<std::atomic<int64_t>*>(address),
870 value);
871}
872
873ExternalReference ExternalReference::atomic_pair_xor_function() {
874 return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_xor)));
875}
876
877static int64_t atomic_pair_exchange(intptr_t address, int value_low,
878 int value_high) {
879 int64_t value =
880 static_cast<int64_t>(value_high) << 32 | (value_low & 0xFFFFFFFF);
881 return std::atomic_exchange(reinterpret_cast<std::atomic<int64_t>*>(address),
882 value);
883}
884
885ExternalReference ExternalReference::atomic_pair_exchange_function() {
886 return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_exchange)));
887}
888
889static uint64_t atomic_pair_compare_exchange(intptr_t address,
890 int old_value_low,
891 int old_value_high,
892 int new_value_low,
893 int new_value_high) {
894 uint64_t old_value = static_cast<uint64_t>(old_value_high) << 32 |
895 (old_value_low & 0xFFFFFFFF);
896 uint64_t new_value = static_cast<uint64_t>(new_value_high) << 32 |
897 (new_value_low & 0xFFFFFFFF);
898 std::atomic_compare_exchange_strong(
899 reinterpret_cast<std::atomic<uint64_t>*>(address), &old_value, new_value);
900 return old_value;
901}
902
903FUNCTION_REFERENCE(atomic_pair_compare_exchange_function,
904 atomic_pair_compare_exchange)
905
906static int EnterMicrotaskContextWrapper(HandleScopeImplementer* hsi,
907 Address raw_context) {
908 Context context = Context::cast(Object(raw_context));
909 hsi->EnterMicrotaskContext(context);
910 return 0;
911}
912
913FUNCTION_REFERENCE(call_enter_context_function, EnterMicrotaskContextWrapper)
914
915bool operator==(ExternalReference lhs, ExternalReference rhs) {
916 return lhs.address() == rhs.address();
917}
918
919bool operator!=(ExternalReference lhs, ExternalReference rhs) {
920 return !(lhs == rhs);
921}
922
923size_t hash_value(ExternalReference reference) {
924 return base::hash<Address>()(reference.address());
925}
926
927std::ostream& operator<<(std::ostream& os, ExternalReference reference) {
928 os << reinterpret_cast<const void*>(reference.address());
929 const Runtime::Function* fn = Runtime::FunctionForEntry(reference.address());
930 if (fn) os << "<" << fn->name << ".entry>";
931 return os;
932}
933
934void abort_with_reason(int reason) {
935 if (IsValidAbortReason(reason)) {
936 const char* message = GetAbortReason(static_cast<AbortReason>(reason));
937 base::OS::PrintError("abort: %s\n", message);
938 } else {
939 base::OS::PrintError("abort: <unknown reason: %d>\n", reason);
940 }
941 base::OS::Abort();
942 UNREACHABLE();
943}
944
945#undef FUNCTION_REFERENCE
946#undef FUNCTION_REFERENCE_WITH_ISOLATE
947#undef FUNCTION_REFERENCE_WITH_TYPE
948
949} // namespace internal
950} // namespace v8
951