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 | |
58 | namespace v8 { |
59 | namespace internal { |
60 | |
61 | // ----------------------------------------------------------------------------- |
62 | // Common double constants. |
63 | |
64 | constexpr double double_min_int_constant = kMinInt; |
65 | constexpr double double_one_half_constant = 0.5; |
66 | constexpr uint64_t double_the_hole_nan_constant = kHoleNanInt64; |
67 | constexpr double double_uint32_bias_constant = |
68 | static_cast<double>(kMaxUInt32) + 1; |
69 | |
70 | constexpr 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 | |
77 | constexpr 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 | |
84 | constexpr struct alignas(16) { |
85 | uint64_t a; |
86 | uint64_t b; |
87 | } double_absolute_constant = {uint64_t{0x7FFFFFFFFFFFFFFF}, |
88 | uint64_t{0x7FFFFFFFFFFFFFFF}}; |
89 | |
90 | constexpr 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 | |
98 | static 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 |
109 | ExternalReference ExternalReference::Create( |
110 | ApiFunction* fun, Type type = ExternalReference::BUILTIN_CALL) { |
111 | return ExternalReference(Redirect(fun->address(), type)); |
112 | } |
113 | |
114 | // static |
115 | ExternalReference ExternalReference::Create(Runtime::FunctionId id) { |
116 | return Create(Runtime::FunctionForId(id)); |
117 | } |
118 | |
119 | // static |
120 | ExternalReference ExternalReference::Create(const Runtime::Function* f) { |
121 | return ExternalReference( |
122 | Redirect(f->entry, BuiltinCallTypeForResultSize(f->result_size))); |
123 | } |
124 | |
125 | // static |
126 | ExternalReference ExternalReference::Create(Address address) { |
127 | return ExternalReference(Redirect(address)); |
128 | } |
129 | |
130 | ExternalReference ExternalReference::isolate_address(Isolate* isolate) { |
131 | return ExternalReference(isolate); |
132 | } |
133 | |
134 | ExternalReference ExternalReference::builtins_address(Isolate* isolate) { |
135 | return ExternalReference(isolate->heap()->builtin_address(0)); |
136 | } |
137 | |
138 | ExternalReference ExternalReference::handle_scope_implementer_address( |
139 | Isolate* isolate) { |
140 | return ExternalReference(isolate->handle_scope_implementer_address()); |
141 | } |
142 | |
143 | ExternalReference ExternalReference::interpreter_dispatch_table_address( |
144 | Isolate* isolate) { |
145 | return ExternalReference(isolate->interpreter()->dispatch_table_address()); |
146 | } |
147 | |
148 | ExternalReference ExternalReference::interpreter_dispatch_counters( |
149 | Isolate* isolate) { |
150 | return ExternalReference( |
151 | isolate->interpreter()->bytecode_dispatch_counters_table()); |
152 | } |
153 | |
154 | ExternalReference |
155 | ExternalReference::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 | |
162 | ExternalReference ExternalReference::bytecode_size_table_address() { |
163 | return ExternalReference( |
164 | interpreter::Bytecodes::bytecode_size_table_address()); |
165 | } |
166 | |
167 | // static |
168 | ExternalReference ExternalReference::Create(StatsCounter* counter) { |
169 | return ExternalReference( |
170 | reinterpret_cast<Address>(counter->GetInternalPointer())); |
171 | } |
172 | |
173 | // static |
174 | ExternalReference ExternalReference::Create(IsolateAddressId id, |
175 | Isolate* isolate) { |
176 | return ExternalReference(isolate->get_address_from_id(id)); |
177 | } |
178 | |
179 | // static |
180 | ExternalReference ExternalReference::Create(const SCTableReference& table_ref) { |
181 | return ExternalReference(table_ref.address()); |
182 | } |
183 | |
184 | namespace { |
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. |
189 | template <typename T> |
190 | constexpr bool AllScalar() { |
191 | return std::is_scalar<T>::value || std::is_void<T>::value; |
192 | } |
193 | |
194 | template <typename T1, typename T2, typename... Rest> |
195 | constexpr 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. |
203 | template <typename T> |
204 | struct IsValidExternalReferenceType; |
205 | |
206 | template <typename Result, typename... Args> |
207 | struct IsValidExternalReferenceType<Result (*)(Args...)> { |
208 | static const bool value = AllScalar<Result, Args...>(); |
209 | }; |
210 | |
211 | template <typename Result, typename Class, typename... Args> |
212 | struct 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 | |
236 | FUNCTION_REFERENCE(incremental_marking_record_write_function, |
237 | IncrementalMarking::RecordWriteFromCode) |
238 | |
239 | ExternalReference ExternalReference::store_buffer_overflow_function() { |
240 | return ExternalReference( |
241 | Redirect(Heap::store_buffer_overflow_function_address())); |
242 | } |
243 | |
244 | FUNCTION_REFERENCE(delete_handle_scope_extensions, |
245 | HandleScope::DeleteExtensions) |
246 | |
247 | FUNCTION_REFERENCE(ephemeron_key_write_barrier_function, |
248 | Heap::EphemeronKeyWriteBarrierFromCode) |
249 | |
250 | FUNCTION_REFERENCE(get_date_field_function, JSDate::GetField) |
251 | |
252 | ExternalReference ExternalReference::date_cache_stamp(Isolate* isolate) { |
253 | return ExternalReference(isolate->date_cache()->stamp_address()); |
254 | } |
255 | |
256 | // static |
257 | ExternalReference |
258 | ExternalReference::runtime_function_table_address_for_unittests( |
259 | Isolate* isolate) { |
260 | return runtime_function_table_address(isolate); |
261 | } |
262 | |
263 | // static |
264 | Address 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 | |
272 | ExternalReference ExternalReference::stress_deopt_count(Isolate* isolate) { |
273 | return ExternalReference(isolate->stress_deopt_count_address()); |
274 | } |
275 | |
276 | ExternalReference ExternalReference::force_slow_path(Isolate* isolate) { |
277 | return ExternalReference(isolate->force_slow_path_address()); |
278 | } |
279 | |
280 | FUNCTION_REFERENCE(new_deoptimizer_function, Deoptimizer::New) |
281 | |
282 | FUNCTION_REFERENCE(compute_output_frames_function, |
283 | Deoptimizer::ComputeOutputFrames) |
284 | |
285 | FUNCTION_REFERENCE(wasm_f32_trunc, wasm::f32_trunc_wrapper) |
286 | FUNCTION_REFERENCE(wasm_f32_floor, wasm::f32_floor_wrapper) |
287 | FUNCTION_REFERENCE(wasm_f32_ceil, wasm::f32_ceil_wrapper) |
288 | FUNCTION_REFERENCE(wasm_f32_nearest_int, wasm::f32_nearest_int_wrapper) |
289 | FUNCTION_REFERENCE(wasm_f64_trunc, wasm::f64_trunc_wrapper) |
290 | FUNCTION_REFERENCE(wasm_f64_floor, wasm::f64_floor_wrapper) |
291 | FUNCTION_REFERENCE(wasm_f64_ceil, wasm::f64_ceil_wrapper) |
292 | FUNCTION_REFERENCE(wasm_f64_nearest_int, wasm::f64_nearest_int_wrapper) |
293 | FUNCTION_REFERENCE(wasm_int64_to_float32, wasm::int64_to_float32_wrapper) |
294 | FUNCTION_REFERENCE(wasm_uint64_to_float32, wasm::uint64_to_float32_wrapper) |
295 | FUNCTION_REFERENCE(wasm_int64_to_float64, wasm::int64_to_float64_wrapper) |
296 | FUNCTION_REFERENCE(wasm_uint64_to_float64, wasm::uint64_to_float64_wrapper) |
297 | FUNCTION_REFERENCE(wasm_float32_to_int64, wasm::float32_to_int64_wrapper) |
298 | FUNCTION_REFERENCE(wasm_float32_to_uint64, wasm::float32_to_uint64_wrapper) |
299 | FUNCTION_REFERENCE(wasm_float64_to_int64, wasm::float64_to_int64_wrapper) |
300 | FUNCTION_REFERENCE(wasm_float64_to_uint64, wasm::float64_to_uint64_wrapper) |
301 | FUNCTION_REFERENCE(wasm_int64_div, wasm::int64_div_wrapper) |
302 | FUNCTION_REFERENCE(wasm_int64_mod, wasm::int64_mod_wrapper) |
303 | FUNCTION_REFERENCE(wasm_uint64_div, wasm::uint64_div_wrapper) |
304 | FUNCTION_REFERENCE(wasm_uint64_mod, wasm::uint64_mod_wrapper) |
305 | FUNCTION_REFERENCE(wasm_word32_ctz, wasm::word32_ctz_wrapper) |
306 | FUNCTION_REFERENCE(wasm_word64_ctz, wasm::word64_ctz_wrapper) |
307 | FUNCTION_REFERENCE(wasm_word32_popcnt, wasm::word32_popcnt_wrapper) |
308 | FUNCTION_REFERENCE(wasm_word64_popcnt, wasm::word64_popcnt_wrapper) |
309 | FUNCTION_REFERENCE(wasm_word32_rol, wasm::word32_rol_wrapper) |
310 | FUNCTION_REFERENCE(wasm_word32_ror, wasm::word32_ror_wrapper) |
311 | FUNCTION_REFERENCE(wasm_memory_copy, wasm::memory_copy_wrapper) |
312 | FUNCTION_REFERENCE(wasm_memory_fill, wasm::memory_fill_wrapper) |
313 | |
314 | static void f64_acos_wrapper(Address data) { |
315 | double input = ReadUnalignedValue<double>(data); |
316 | WriteUnalignedValue(data, base::ieee754::acos(input)); |
317 | } |
318 | |
319 | FUNCTION_REFERENCE(f64_acos_wrapper_function, f64_acos_wrapper) |
320 | |
321 | static void f64_asin_wrapper(Address data) { |
322 | double input = ReadUnalignedValue<double>(data); |
323 | WriteUnalignedValue<double>(data, base::ieee754::asin(input)); |
324 | } |
325 | |
326 | FUNCTION_REFERENCE(f64_asin_wrapper_function, f64_asin_wrapper) |
327 | |
328 | FUNCTION_REFERENCE(wasm_float64_pow, wasm::float64_pow_wrapper) |
329 | |
330 | static 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 | |
336 | FUNCTION_REFERENCE(f64_mod_wrapper_function, f64_mod_wrapper) |
337 | |
338 | FUNCTION_REFERENCE(wasm_call_trap_callback_for_testing, |
339 | wasm::call_trap_callback_for_testing) |
340 | |
341 | FUNCTION_REFERENCE(log_enter_external_function, Logger::EnterExternal) |
342 | FUNCTION_REFERENCE(log_leave_external_function, Logger::LeaveExternal) |
343 | |
344 | ExternalReference ExternalReference::isolate_root(Isolate* isolate) { |
345 | return ExternalReference(isolate->isolate_root()); |
346 | } |
347 | |
348 | ExternalReference ExternalReference::allocation_sites_list_address( |
349 | Isolate* isolate) { |
350 | return ExternalReference(isolate->heap()->allocation_sites_list_address()); |
351 | } |
352 | |
353 | ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) { |
354 | return ExternalReference(isolate->stack_guard()->address_of_jslimit()); |
355 | } |
356 | |
357 | ExternalReference ExternalReference::address_of_real_stack_limit( |
358 | Isolate* isolate) { |
359 | return ExternalReference(isolate->stack_guard()->address_of_real_jslimit()); |
360 | } |
361 | |
362 | ExternalReference ExternalReference::store_buffer_top(Isolate* isolate) { |
363 | return ExternalReference(isolate->heap()->store_buffer_top_address()); |
364 | } |
365 | |
366 | ExternalReference ExternalReference::heap_is_marking_flag_address( |
367 | Isolate* isolate) { |
368 | return ExternalReference(isolate->heap()->IsMarkingFlagAddress()); |
369 | } |
370 | |
371 | ExternalReference ExternalReference::new_space_allocation_top_address( |
372 | Isolate* isolate) { |
373 | return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress()); |
374 | } |
375 | |
376 | ExternalReference ExternalReference::new_space_allocation_limit_address( |
377 | Isolate* isolate) { |
378 | return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress()); |
379 | } |
380 | |
381 | ExternalReference ExternalReference::old_space_allocation_top_address( |
382 | Isolate* isolate) { |
383 | return ExternalReference(isolate->heap()->OldSpaceAllocationTopAddress()); |
384 | } |
385 | |
386 | ExternalReference ExternalReference::old_space_allocation_limit_address( |
387 | Isolate* isolate) { |
388 | return ExternalReference(isolate->heap()->OldSpaceAllocationLimitAddress()); |
389 | } |
390 | |
391 | ExternalReference ExternalReference::handle_scope_level_address( |
392 | Isolate* isolate) { |
393 | return ExternalReference(HandleScope::current_level_address(isolate)); |
394 | } |
395 | |
396 | ExternalReference ExternalReference::handle_scope_next_address( |
397 | Isolate* isolate) { |
398 | return ExternalReference(HandleScope::current_next_address(isolate)); |
399 | } |
400 | |
401 | ExternalReference ExternalReference::handle_scope_limit_address( |
402 | Isolate* isolate) { |
403 | return ExternalReference(HandleScope::current_limit_address(isolate)); |
404 | } |
405 | |
406 | ExternalReference ExternalReference::scheduled_exception_address( |
407 | Isolate* isolate) { |
408 | return ExternalReference(isolate->scheduled_exception_address()); |
409 | } |
410 | |
411 | ExternalReference ExternalReference::address_of_pending_message_obj( |
412 | Isolate* isolate) { |
413 | return ExternalReference(isolate->pending_message_obj_address()); |
414 | } |
415 | |
416 | FUNCTION_REFERENCE(abort_with_reason, i::abort_with_reason) |
417 | |
418 | ExternalReference |
419 | ExternalReference::address_of_harmony_await_optimization_flag() { |
420 | return ExternalReference(&FLAG_harmony_await_optimization); |
421 | } |
422 | |
423 | ExternalReference ExternalReference::address_of_min_int() { |
424 | return ExternalReference(reinterpret_cast<Address>(&double_min_int_constant)); |
425 | } |
426 | |
427 | ExternalReference |
428 | ExternalReference::address_of_mock_arraybuffer_allocator_flag() { |
429 | return ExternalReference(&FLAG_mock_arraybuffer_allocator); |
430 | } |
431 | |
432 | ExternalReference ExternalReference::address_of_runtime_stats_flag() { |
433 | return ExternalReference(&TracingFlags::runtime_stats); |
434 | } |
435 | |
436 | ExternalReference ExternalReference::address_of_one_half() { |
437 | return ExternalReference( |
438 | reinterpret_cast<Address>(&double_one_half_constant)); |
439 | } |
440 | |
441 | ExternalReference ExternalReference::address_of_the_hole_nan() { |
442 | return ExternalReference( |
443 | reinterpret_cast<Address>(&double_the_hole_nan_constant)); |
444 | } |
445 | |
446 | ExternalReference ExternalReference::address_of_uint32_bias() { |
447 | return ExternalReference( |
448 | reinterpret_cast<Address>(&double_uint32_bias_constant)); |
449 | } |
450 | |
451 | ExternalReference ExternalReference::address_of_float_abs_constant() { |
452 | return ExternalReference(reinterpret_cast<Address>(&float_absolute_constant)); |
453 | } |
454 | |
455 | ExternalReference ExternalReference::address_of_float_neg_constant() { |
456 | return ExternalReference(reinterpret_cast<Address>(&float_negate_constant)); |
457 | } |
458 | |
459 | ExternalReference ExternalReference::address_of_double_abs_constant() { |
460 | return ExternalReference( |
461 | reinterpret_cast<Address>(&double_absolute_constant)); |
462 | } |
463 | |
464 | ExternalReference ExternalReference::address_of_double_neg_constant() { |
465 | return ExternalReference(reinterpret_cast<Address>(&double_negate_constant)); |
466 | } |
467 | |
468 | ExternalReference ExternalReference::is_profiling_address(Isolate* isolate) { |
469 | return ExternalReference(isolate->is_profiling_address()); |
470 | } |
471 | |
472 | ExternalReference 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 | |
479 | ExternalReference 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 | |
506 | FUNCTION_REFERENCE_WITH_ISOLATE(re_check_stack_guard_state, re_stack_check_func) |
507 | #undef re_stack_check_func |
508 | |
509 | FUNCTION_REFERENCE_WITH_ISOLATE(re_grow_stack, |
510 | NativeRegExpMacroAssembler::GrowStack) |
511 | |
512 | FUNCTION_REFERENCE_WITH_ISOLATE( |
513 | re_case_insensitive_compare_uc16, |
514 | NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16) |
515 | |
516 | ExternalReference ExternalReference::re_word_character_map(Isolate* isolate) { |
517 | return ExternalReference( |
518 | NativeRegExpMacroAssembler::word_character_map_address()); |
519 | } |
520 | |
521 | ExternalReference ExternalReference::address_of_static_offsets_vector( |
522 | Isolate* isolate) { |
523 | return ExternalReference( |
524 | reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector())); |
525 | } |
526 | |
527 | ExternalReference ExternalReference::address_of_regexp_stack_limit( |
528 | Isolate* isolate) { |
529 | return ExternalReference(isolate->regexp_stack()->limit_address()); |
530 | } |
531 | |
532 | ExternalReference ExternalReference::address_of_regexp_stack_memory_address( |
533 | Isolate* isolate) { |
534 | return ExternalReference(isolate->regexp_stack()->memory_address()); |
535 | } |
536 | |
537 | ExternalReference ExternalReference::address_of_regexp_stack_memory_size( |
538 | Isolate* isolate) { |
539 | return ExternalReference(isolate->regexp_stack()->memory_size_address()); |
540 | } |
541 | |
542 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_acos_function, base::ieee754::acos, |
543 | BUILTIN_FP_CALL) |
544 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_acosh_function, base::ieee754::acosh, |
545 | BUILTIN_FP_FP_CALL) |
546 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_asin_function, base::ieee754::asin, |
547 | BUILTIN_FP_CALL) |
548 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_asinh_function, base::ieee754::asinh, |
549 | BUILTIN_FP_FP_CALL) |
550 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_atan_function, base::ieee754::atan, |
551 | BUILTIN_FP_CALL) |
552 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_atanh_function, base::ieee754::atanh, |
553 | BUILTIN_FP_FP_CALL) |
554 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_atan2_function, base::ieee754::atan2, |
555 | BUILTIN_FP_FP_CALL) |
556 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_cbrt_function, base::ieee754::cbrt, |
557 | BUILTIN_FP_FP_CALL) |
558 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_cos_function, base::ieee754::cos, |
559 | BUILTIN_FP_CALL) |
560 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_cosh_function, base::ieee754::cosh, |
561 | BUILTIN_FP_CALL) |
562 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_exp_function, base::ieee754::exp, |
563 | BUILTIN_FP_CALL) |
564 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_expm1_function, base::ieee754::expm1, |
565 | BUILTIN_FP_FP_CALL) |
566 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_log_function, base::ieee754::log, |
567 | BUILTIN_FP_CALL) |
568 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_log1p_function, base::ieee754::log1p, |
569 | BUILTIN_FP_CALL) |
570 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_log10_function, base::ieee754::log10, |
571 | BUILTIN_FP_CALL) |
572 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_log2_function, base::ieee754::log2, |
573 | BUILTIN_FP_CALL) |
574 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_sin_function, base::ieee754::sin, |
575 | BUILTIN_FP_CALL) |
576 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_sinh_function, base::ieee754::sinh, |
577 | BUILTIN_FP_CALL) |
578 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_tan_function, base::ieee754::tan, |
579 | BUILTIN_FP_CALL) |
580 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_tanh_function, base::ieee754::tanh, |
581 | BUILTIN_FP_CALL) |
582 | FUNCTION_REFERENCE_WITH_TYPE(ieee754_pow_function, base::ieee754::pow, |
583 | BUILTIN_FP_FP_CALL) |
584 | |
585 | void* libc_memchr(void* string, int character, size_t search_length) { |
586 | return memchr(string, character, search_length); |
587 | } |
588 | |
589 | FUNCTION_REFERENCE(libc_memchr_function, libc_memchr) |
590 | |
591 | void* libc_memcpy(void* dest, const void* src, size_t n) { |
592 | return memcpy(dest, src, n); |
593 | } |
594 | |
595 | FUNCTION_REFERENCE(libc_memcpy_function, libc_memcpy) |
596 | |
597 | void* libc_memmove(void* dest, const void* src, size_t n) { |
598 | return memmove(dest, src, n); |
599 | } |
600 | |
601 | FUNCTION_REFERENCE(libc_memmove_function, libc_memmove) |
602 | |
603 | void* 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 | |
608 | FUNCTION_REFERENCE(libc_memset_function, libc_memset) |
609 | |
610 | ExternalReference ExternalReference::printf_function() { |
611 | return ExternalReference(Redirect(FUNCTION_ADDR(std::printf))); |
612 | } |
613 | |
614 | FUNCTION_REFERENCE(refill_math_random, MathRandom::RefillCache) |
615 | |
616 | template <typename SubjectChar, typename PatternChar> |
617 | ExternalReference ExternalReference::search_string_raw() { |
618 | auto f = SearchStringRaw<SubjectChar, PatternChar>; |
619 | return ExternalReference(Redirect(FUNCTION_ADDR(f))); |
620 | } |
621 | |
622 | FUNCTION_REFERENCE(jsarray_array_join_concat_to_sequential_string, |
623 | JSArray::ArrayJoinConcatToSequentialString) |
624 | |
625 | ExternalReference ExternalReference::search_string_raw_one_one() { |
626 | return search_string_raw<const uint8_t, const uint8_t>(); |
627 | } |
628 | |
629 | ExternalReference ExternalReference::search_string_raw_one_two() { |
630 | return search_string_raw<const uint8_t, const uc16>(); |
631 | } |
632 | |
633 | ExternalReference ExternalReference::search_string_raw_two_one() { |
634 | return search_string_raw<const uc16, const uint8_t>(); |
635 | } |
636 | |
637 | ExternalReference ExternalReference::search_string_raw_two_two() { |
638 | return search_string_raw<const uc16, const uc16>(); |
639 | } |
640 | |
641 | FUNCTION_REFERENCE(orderedhashmap_gethash_raw, OrderedHashMap::GetHash) |
642 | |
643 | Address GetOrCreateHash(Isolate* isolate, Address raw_key) { |
644 | DisallowHeapAllocation no_gc; |
645 | return Object(raw_key)->GetOrCreateHash(isolate).ptr(); |
646 | } |
647 | |
648 | FUNCTION_REFERENCE(get_or_create_hash_raw, GetOrCreateHash) |
649 | |
650 | static Address JSReceiverCreateIdentityHash(Isolate* isolate, Address raw_key) { |
651 | JSReceiver key = JSReceiver::cast(Object(raw_key)); |
652 | return JSReceiver::CreateIdentityHash(isolate, key).ptr(); |
653 | } |
654 | |
655 | FUNCTION_REFERENCE(jsreceiver_create_identity_hash, |
656 | JSReceiverCreateIdentityHash) |
657 | |
658 | static uint32_t ComputeSeededIntegerHash(Isolate* isolate, uint32_t key) { |
659 | DisallowHeapAllocation no_gc; |
660 | return ComputeSeededHash(key, HashSeed(isolate)); |
661 | } |
662 | |
663 | FUNCTION_REFERENCE(compute_integer_hash, ComputeSeededIntegerHash) |
664 | FUNCTION_REFERENCE(copy_fast_number_jsarray_elements_to_typed_array, |
665 | CopyFastNumberJSArrayElementsToTypedArray) |
666 | FUNCTION_REFERENCE(copy_typed_array_elements_to_typed_array, |
667 | CopyTypedArrayElementsToTypedArray) |
668 | FUNCTION_REFERENCE(copy_typed_array_elements_slice, CopyTypedArrayElementsSlice) |
669 | FUNCTION_REFERENCE(try_internalize_string_function, |
670 | StringTable::LookupStringIfExists_NoAllocate) |
671 | |
672 | static 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 | |
679 | FUNCTION_REFERENCE(smi_lexicographic_compare_function, |
680 | LexicographicCompareWrapper) |
681 | |
682 | FUNCTION_REFERENCE(check_object_type, CheckObjectType) |
683 | |
684 | #ifdef V8_INTL_SUPPORT |
685 | |
686 | static 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 | } |
691 | FUNCTION_REFERENCE(intl_convert_one_byte_to_lower, ConvertOneByteToLower) |
692 | |
693 | ExternalReference 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. |
700 | template ExternalReference |
701 | ExternalReference::search_string_raw<const uint8_t, const uint8_t>(); |
702 | template ExternalReference |
703 | ExternalReference::search_string_raw<const uint8_t, const uc16>(); |
704 | template ExternalReference |
705 | ExternalReference::search_string_raw<const uc16, const uint8_t>(); |
706 | template ExternalReference |
707 | ExternalReference::search_string_raw<const uc16, const uc16>(); |
708 | |
709 | ExternalReference ExternalReference::FromRawAddress(Address address) { |
710 | return ExternalReference(address); |
711 | } |
712 | |
713 | ExternalReference ExternalReference::cpu_features() { |
714 | DCHECK(CpuFeatures::initialized_); |
715 | return ExternalReference(&CpuFeatures::supported_); |
716 | } |
717 | |
718 | ExternalReference ExternalReference::promise_hook_address(Isolate* isolate) { |
719 | return ExternalReference(isolate->promise_hook_address()); |
720 | } |
721 | |
722 | ExternalReference ExternalReference::async_event_delegate_address( |
723 | Isolate* isolate) { |
724 | return ExternalReference(isolate->async_event_delegate_address()); |
725 | } |
726 | |
727 | ExternalReference |
728 | ExternalReference::promise_hook_or_async_event_delegate_address( |
729 | Isolate* isolate) { |
730 | return ExternalReference( |
731 | isolate->promise_hook_or_async_event_delegate_address()); |
732 | } |
733 | |
734 | ExternalReference 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 | |
742 | ExternalReference ExternalReference::debug_execution_mode_address( |
743 | Isolate* isolate) { |
744 | return ExternalReference(isolate->debug_execution_mode_address()); |
745 | } |
746 | |
747 | ExternalReference ExternalReference::debug_is_active_address(Isolate* isolate) { |
748 | return ExternalReference(isolate->debug()->is_active_address()); |
749 | } |
750 | |
751 | ExternalReference ExternalReference::debug_hook_on_function_call_address( |
752 | Isolate* isolate) { |
753 | return ExternalReference(isolate->debug()->hook_on_function_call_address()); |
754 | } |
755 | |
756 | ExternalReference ExternalReference::runtime_function_table_address( |
757 | Isolate* isolate) { |
758 | return ExternalReference( |
759 | const_cast<Runtime::Function*>(Runtime::RuntimeFunctionTable(isolate))); |
760 | } |
761 | |
762 | static Address InvalidatePrototypeChainsWrapper(Address raw_map) { |
763 | Map map = Map::cast(Object(raw_map)); |
764 | return JSObject::InvalidatePrototypeChains(map).ptr(); |
765 | } |
766 | |
767 | FUNCTION_REFERENCE(invalidate_prototype_chains_function, |
768 | InvalidatePrototypeChainsWrapper) |
769 | |
770 | double modulo_double_double(double x, double y) { return Modulo(x, y); } |
771 | |
772 | FUNCTION_REFERENCE_WITH_TYPE(mod_two_doubles_operation, modulo_double_double, |
773 | BUILTIN_FP_FP_CALL) |
774 | |
775 | ExternalReference ExternalReference::debug_suspended_generator_address( |
776 | Isolate* isolate) { |
777 | return ExternalReference(isolate->debug()->suspended_generator_address()); |
778 | } |
779 | |
780 | ExternalReference ExternalReference::debug_restart_fp_address( |
781 | Isolate* isolate) { |
782 | return ExternalReference(isolate->debug()->restart_fp_address()); |
783 | } |
784 | |
785 | ExternalReference 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 | |
791 | ExternalReference 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 | |
797 | FUNCTION_REFERENCE(call_enqueue_microtask_function, |
798 | MicrotaskQueue::CallEnqueueMicrotask) |
799 | |
800 | static int64_t atomic_pair_load(intptr_t address) { |
801 | return std::atomic_load(reinterpret_cast<std::atomic<int64_t>*>(address)); |
802 | } |
803 | |
804 | ExternalReference ExternalReference::atomic_pair_load_function() { |
805 | return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_load))); |
806 | } |
807 | |
808 | static 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 | |
814 | ExternalReference ExternalReference::atomic_pair_store_function() { |
815 | return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_store))); |
816 | } |
817 | |
818 | static 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 | |
826 | ExternalReference ExternalReference::atomic_pair_add_function() { |
827 | return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_add))); |
828 | } |
829 | |
830 | static 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 | |
838 | ExternalReference ExternalReference::atomic_pair_sub_function() { |
839 | return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_sub))); |
840 | } |
841 | |
842 | static 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 | |
850 | ExternalReference ExternalReference::atomic_pair_and_function() { |
851 | return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_and))); |
852 | } |
853 | |
854 | static 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 | |
861 | ExternalReference ExternalReference::atomic_pair_or_function() { |
862 | return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_or))); |
863 | } |
864 | |
865 | static 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 | |
873 | ExternalReference ExternalReference::atomic_pair_xor_function() { |
874 | return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_xor))); |
875 | } |
876 | |
877 | static 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 | |
885 | ExternalReference ExternalReference::atomic_pair_exchange_function() { |
886 | return ExternalReference(Redirect(FUNCTION_ADDR(atomic_pair_exchange))); |
887 | } |
888 | |
889 | static 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 | |
903 | FUNCTION_REFERENCE(atomic_pair_compare_exchange_function, |
904 | atomic_pair_compare_exchange) |
905 | |
906 | static 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 | |
913 | FUNCTION_REFERENCE(call_enter_context_function, EnterMicrotaskContextWrapper) |
914 | |
915 | bool operator==(ExternalReference lhs, ExternalReference rhs) { |
916 | return lhs.address() == rhs.address(); |
917 | } |
918 | |
919 | bool operator!=(ExternalReference lhs, ExternalReference rhs) { |
920 | return !(lhs == rhs); |
921 | } |
922 | |
923 | size_t hash_value(ExternalReference reference) { |
924 | return base::hash<Address>()(reference.address()); |
925 | } |
926 | |
927 | std::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 | |
934 | void 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 | |