v8/src/external-reference.cc
Sigurd Schneider ba39d635de [turbofan] Support kRootRegisterBias on all platforms
We had a kRootRegisterBias on x64 before. This CL ports the feature to
all other platforms as well. The root register bias is helpful to adjust
the value of the root register, which allows to better utilize signed
immediate offset constants in load instructions.

We currently use a separate add instruction to add kRootRegisterBias
in the code that initializes the root register. This could be improved
by adding a custom relocation mode ensuring that instead of the root
address, the root address plus the bias is inserted (and in this way
the add instruction can be omitted).

Bug: v8:6666
Change-Id: I55cf02ab85d11e3c6d0d83a8f7905dbf924890f1
Reviewed-on: https://chromium-review.googlesource.com/1113539
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54023}
2018-06-26 09:59:00 +00:00

982 lines
32 KiB
C++

// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/external-reference.h"
#include "src/api.h"
#include "src/base/ieee754.h"
#include "src/codegen.h"
#include "src/compiler/code-assembler.h"
#include "src/counters.h"
#include "src/debug/debug.h"
#include "src/deoptimizer.h"
#include "src/elements.h"
#include "src/heap/heap.h"
#include "src/ic/stub-cache.h"
#include "src/interpreter/interpreter.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/regexp/regexp-stack.h"
#include "src/simulator-base.h"
#include "src/string-search.h"
#include "src/wasm/wasm-external-refs.h"
// Include native regexp-macro-assembler.
#ifndef V8_INTERPRETED_REGEXP
#if V8_TARGET_ARCH_IA32
#include "src/regexp/ia32/regexp-macro-assembler-ia32.h" // NOLINT
#elif V8_TARGET_ARCH_X64
#include "src/regexp/x64/regexp-macro-assembler-x64.h" // NOLINT
#elif V8_TARGET_ARCH_ARM64
#include "src/regexp/arm64/regexp-macro-assembler-arm64.h" // NOLINT
#elif V8_TARGET_ARCH_ARM
#include "src/regexp/arm/regexp-macro-assembler-arm.h" // NOLINT
#elif V8_TARGET_ARCH_PPC
#include "src/regexp/ppc/regexp-macro-assembler-ppc.h" // NOLINT
#elif V8_TARGET_ARCH_MIPS
#include "src/regexp/mips/regexp-macro-assembler-mips.h" // NOLINT
#elif V8_TARGET_ARCH_MIPS64
#include "src/regexp/mips64/regexp-macro-assembler-mips64.h" // NOLINT
#elif V8_TARGET_ARCH_S390
#include "src/regexp/s390/regexp-macro-assembler-s390.h" // NOLINT
#else // Unknown architecture.
#error "Unknown architecture."
#endif // Target architecture.
#endif // V8_INTERPRETED_REGEXP
#ifdef V8_INTL_SUPPORT
#include "src/intl.h"
#endif // V8_INTL_SUPPORT
namespace v8 {
namespace internal {
// -----------------------------------------------------------------------------
// Common double constants.
constexpr double double_min_int_constant = kMinInt;
constexpr double double_one_half_constant = 0.5;
constexpr double double_minus_one_half_constant = -0.5;
constexpr double double_negative_infinity_constant = -V8_INFINITY;
constexpr uint64_t double_the_hole_nan_constant = kHoleNanInt64;
constexpr double double_uint32_bias_constant =
static_cast<double>(kMaxUInt32) + 1;
constexpr struct V8_ALIGNED(16) {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
} float_absolute_constant = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
constexpr struct V8_ALIGNED(16) {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
} float_negate_constant = {0x80000000, 0x80000000, 0x80000000, 0x80000000};
constexpr struct V8_ALIGNED(16) {
uint64_t a;
uint64_t b;
} double_absolute_constant = {uint64_t{0x7FFFFFFFFFFFFFFF},
uint64_t{0x7FFFFFFFFFFFFFFF}};
constexpr struct V8_ALIGNED(16) {
uint64_t a;
uint64_t b;
} double_negate_constant = {uint64_t{0x8000000000000000},
uint64_t{0x8000000000000000}};
// Implementation of ExternalReference
static ExternalReference::Type BuiltinCallTypeForResultSize(int result_size) {
switch (result_size) {
case 1:
return ExternalReference::BUILTIN_CALL;
case 2:
return ExternalReference::BUILTIN_CALL_PAIR;
}
UNREACHABLE();
}
// static
ExternalReference ExternalReference::Create(
ApiFunction* fun, Type type = ExternalReference::BUILTIN_CALL) {
return ExternalReference(Redirect(fun->address(), type));
}
// static
ExternalReference ExternalReference::Create(Runtime::FunctionId id) {
return Create(Runtime::FunctionForId(id));
}
// static
ExternalReference ExternalReference::Create(const Runtime::Function* f) {
return ExternalReference(
Redirect(f->entry, BuiltinCallTypeForResultSize(f->result_size)));
}
// static
ExternalReference ExternalReference::Create(Address address) {
return ExternalReference(Redirect(address));
}
ExternalReference ExternalReference::isolate_address(Isolate* isolate) {
return ExternalReference(isolate);
}
ExternalReference ExternalReference::builtins_address(Isolate* isolate) {
return ExternalReference(isolate->heap()->builtin_address(0));
}
ExternalReference ExternalReference::handle_scope_implementer_address(
Isolate* isolate) {
return ExternalReference(isolate->handle_scope_implementer_address());
}
ExternalReference ExternalReference::pending_microtask_count_address(
Isolate* isolate) {
return ExternalReference(isolate->pending_microtask_count_address());
}
ExternalReference ExternalReference::interpreter_dispatch_table_address(
Isolate* isolate) {
return ExternalReference(isolate->interpreter()->dispatch_table_address());
}
ExternalReference ExternalReference::interpreter_dispatch_counters(
Isolate* isolate) {
return ExternalReference(
isolate->interpreter()->bytecode_dispatch_counters_table());
}
ExternalReference ExternalReference::bytecode_size_table_address() {
return ExternalReference(
interpreter::Bytecodes::bytecode_size_table_address());
}
// static
ExternalReference ExternalReference::Create(StatsCounter* counter) {
return ExternalReference(
reinterpret_cast<Address>(counter->GetInternalPointer()));
}
// static
ExternalReference ExternalReference::Create(IsolateAddressId id,
Isolate* isolate) {
return ExternalReference(isolate->get_address_from_id(id));
}
// static
ExternalReference ExternalReference::Create(const SCTableReference& table_ref) {
return ExternalReference(table_ref.address());
}
ExternalReference
ExternalReference::incremental_marking_record_write_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(IncrementalMarking::RecordWriteFromCode)));
}
ExternalReference ExternalReference::store_buffer_overflow_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(StoreBuffer::StoreBufferOverflow)));
}
ExternalReference ExternalReference::delete_handle_scope_extensions() {
return ExternalReference(
Redirect(FUNCTION_ADDR(HandleScope::DeleteExtensions)));
}
ExternalReference ExternalReference::get_date_field_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(JSDate::GetField)));
}
ExternalReference ExternalReference::date_cache_stamp(Isolate* isolate) {
return ExternalReference(isolate->date_cache()->stamp_address());
}
// static
ExternalReference
ExternalReference::runtime_function_table_address_for_unittests(
Isolate* isolate) {
return runtime_function_table_address(isolate);
}
// static
Address ExternalReference::Redirect(Address address, Type type) {
#ifdef USE_SIMULATOR
return SimulatorBase::RedirectExternalReference(address, type);
#else
return address;
#endif
}
ExternalReference ExternalReference::stress_deopt_count(Isolate* isolate) {
return ExternalReference(isolate->stress_deopt_count_address());
}
ExternalReference ExternalReference::force_slow_path(Isolate* isolate) {
return ExternalReference(isolate->force_slow_path_address());
}
ExternalReference ExternalReference::new_deoptimizer_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(Deoptimizer::New)));
}
ExternalReference ExternalReference::compute_output_frames_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(Deoptimizer::ComputeOutputFrames)));
}
ExternalReference ExternalReference::wasm_f32_trunc() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::f32_trunc_wrapper)));
}
ExternalReference ExternalReference::wasm_f32_floor() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::f32_floor_wrapper)));
}
ExternalReference ExternalReference::wasm_f32_ceil() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::f32_ceil_wrapper)));
}
ExternalReference ExternalReference::wasm_f32_nearest_int() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::f32_nearest_int_wrapper)));
}
ExternalReference ExternalReference::wasm_f64_trunc() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::f64_trunc_wrapper)));
}
ExternalReference ExternalReference::wasm_f64_floor() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::f64_floor_wrapper)));
}
ExternalReference ExternalReference::wasm_f64_ceil() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::f64_ceil_wrapper)));
}
ExternalReference ExternalReference::wasm_f64_nearest_int() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::f64_nearest_int_wrapper)));
}
ExternalReference ExternalReference::wasm_int64_to_float32() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::int64_to_float32_wrapper)));
}
ExternalReference ExternalReference::wasm_uint64_to_float32() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::uint64_to_float32_wrapper)));
}
ExternalReference ExternalReference::wasm_int64_to_float64() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::int64_to_float64_wrapper)));
}
ExternalReference ExternalReference::wasm_uint64_to_float64() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::uint64_to_float64_wrapper)));
}
ExternalReference ExternalReference::wasm_float32_to_int64() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::float32_to_int64_wrapper)));
}
ExternalReference ExternalReference::wasm_float32_to_uint64() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::float32_to_uint64_wrapper)));
}
ExternalReference ExternalReference::wasm_float64_to_int64() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::float64_to_int64_wrapper)));
}
ExternalReference ExternalReference::wasm_float64_to_uint64() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::float64_to_uint64_wrapper)));
}
ExternalReference ExternalReference::wasm_int64_div() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::int64_div_wrapper)));
}
ExternalReference ExternalReference::wasm_int64_mod() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::int64_mod_wrapper)));
}
ExternalReference ExternalReference::wasm_uint64_div() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::uint64_div_wrapper)));
}
ExternalReference ExternalReference::wasm_uint64_mod() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::uint64_mod_wrapper)));
}
ExternalReference ExternalReference::wasm_word32_ctz() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::word32_ctz_wrapper)));
}
ExternalReference ExternalReference::wasm_word64_ctz() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::word64_ctz_wrapper)));
}
ExternalReference ExternalReference::wasm_word32_popcnt() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::word32_popcnt_wrapper)));
}
ExternalReference ExternalReference::wasm_word64_popcnt() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::word64_popcnt_wrapper)));
}
ExternalReference ExternalReference::wasm_word32_rol() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::word32_rol_wrapper)));
}
ExternalReference ExternalReference::wasm_word32_ror() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::word32_ror_wrapper)));
}
static void f64_acos_wrapper(Address data) {
double input = ReadUnalignedValue<double>(data);
WriteUnalignedValue(data, base::ieee754::acos(input));
}
ExternalReference ExternalReference::f64_acos_wrapper_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(f64_acos_wrapper)));
}
static void f64_asin_wrapper(Address data) {
double input = ReadUnalignedValue<double>(data);
WriteUnalignedValue<double>(data, base::ieee754::asin(input));
}
ExternalReference ExternalReference::f64_asin_wrapper_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(f64_asin_wrapper)));
}
ExternalReference ExternalReference::wasm_float64_pow() {
return ExternalReference(Redirect(FUNCTION_ADDR(wasm::float64_pow_wrapper)));
}
ExternalReference ExternalReference::wasm_set_thread_in_wasm_flag() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::set_thread_in_wasm_flag)));
}
ExternalReference ExternalReference::wasm_clear_thread_in_wasm_flag() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::clear_thread_in_wasm_flag)));
}
static void f64_mod_wrapper(Address data) {
double dividend = ReadUnalignedValue<double>(data);
double divisor = ReadUnalignedValue<double>(data + sizeof(dividend));
WriteUnalignedValue<double>(data, Modulo(dividend, divisor));
}
ExternalReference ExternalReference::f64_mod_wrapper_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(f64_mod_wrapper)));
}
ExternalReference ExternalReference::wasm_call_trap_callback_for_testing() {
return ExternalReference(
Redirect(FUNCTION_ADDR(wasm::call_trap_callback_for_testing)));
}
ExternalReference ExternalReference::log_enter_external_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(Logger::EnterExternal)));
}
ExternalReference ExternalReference::log_leave_external_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(Logger::LeaveExternal)));
}
ExternalReference ExternalReference::roots_array_start(Isolate* isolate) {
return ExternalReference(isolate->heap()->roots_array_start());
}
ExternalReference ExternalReference::allocation_sites_list_address(
Isolate* isolate) {
return ExternalReference(isolate->heap()->allocation_sites_list_address());
}
ExternalReference ExternalReference::address_of_stack_limit(Isolate* isolate) {
return ExternalReference(isolate->stack_guard()->address_of_jslimit());
}
ExternalReference ExternalReference::address_of_real_stack_limit(
Isolate* isolate) {
return ExternalReference(isolate->stack_guard()->address_of_real_jslimit());
}
ExternalReference ExternalReference::store_buffer_top(Isolate* isolate) {
return ExternalReference(isolate->heap()->store_buffer_top_address());
}
ExternalReference ExternalReference::heap_is_marking_flag_address(
Isolate* isolate) {
return ExternalReference(isolate->heap()->IsMarkingFlagAddress());
}
ExternalReference ExternalReference::new_space_allocation_top_address(
Isolate* isolate) {
return ExternalReference(isolate->heap()->NewSpaceAllocationTopAddress());
}
ExternalReference ExternalReference::new_space_allocation_limit_address(
Isolate* isolate) {
return ExternalReference(isolate->heap()->NewSpaceAllocationLimitAddress());
}
ExternalReference ExternalReference::old_space_allocation_top_address(
Isolate* isolate) {
return ExternalReference(isolate->heap()->OldSpaceAllocationTopAddress());
}
ExternalReference ExternalReference::old_space_allocation_limit_address(
Isolate* isolate) {
return ExternalReference(isolate->heap()->OldSpaceAllocationLimitAddress());
}
ExternalReference ExternalReference::handle_scope_level_address(
Isolate* isolate) {
return ExternalReference(HandleScope::current_level_address(isolate));
}
ExternalReference ExternalReference::handle_scope_next_address(
Isolate* isolate) {
return ExternalReference(HandleScope::current_next_address(isolate));
}
ExternalReference ExternalReference::handle_scope_limit_address(
Isolate* isolate) {
return ExternalReference(HandleScope::current_limit_address(isolate));
}
ExternalReference ExternalReference::scheduled_exception_address(
Isolate* isolate) {
return ExternalReference(isolate->scheduled_exception_address());
}
ExternalReference ExternalReference::address_of_pending_message_obj(
Isolate* isolate) {
return ExternalReference(isolate->pending_message_obj_address());
}
ExternalReference ExternalReference::address_of_min_int() {
return ExternalReference(reinterpret_cast<Address>(&double_min_int_constant));
}
ExternalReference ExternalReference::address_of_one_half() {
return ExternalReference(
reinterpret_cast<Address>(&double_one_half_constant));
}
ExternalReference ExternalReference::address_of_minus_one_half() {
return ExternalReference(
reinterpret_cast<Address>(&double_minus_one_half_constant));
}
ExternalReference ExternalReference::address_of_negative_infinity() {
return ExternalReference(
reinterpret_cast<Address>(&double_negative_infinity_constant));
}
ExternalReference ExternalReference::address_of_the_hole_nan() {
return ExternalReference(
reinterpret_cast<Address>(&double_the_hole_nan_constant));
}
ExternalReference ExternalReference::address_of_uint32_bias() {
return ExternalReference(
reinterpret_cast<Address>(&double_uint32_bias_constant));
}
ExternalReference ExternalReference::address_of_float_abs_constant() {
return ExternalReference(reinterpret_cast<Address>(&float_absolute_constant));
}
ExternalReference ExternalReference::address_of_float_neg_constant() {
return ExternalReference(reinterpret_cast<Address>(&float_negate_constant));
}
ExternalReference ExternalReference::address_of_double_abs_constant() {
return ExternalReference(
reinterpret_cast<Address>(&double_absolute_constant));
}
ExternalReference ExternalReference::address_of_double_neg_constant() {
return ExternalReference(reinterpret_cast<Address>(&double_negate_constant));
}
ExternalReference ExternalReference::is_profiling_address(Isolate* isolate) {
return ExternalReference(isolate->is_profiling_address());
}
ExternalReference ExternalReference::invoke_function_callback() {
Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL;
ApiFunction thunk_fun(thunk_address);
return ExternalReference::Create(&thunk_fun, thunk_type);
}
ExternalReference ExternalReference::invoke_accessor_getter_callback() {
Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
ExternalReference::Type thunk_type = ExternalReference::PROFILING_GETTER_CALL;
ApiFunction thunk_fun(thunk_address);
return ExternalReference::Create(&thunk_fun, thunk_type);
}
#ifndef V8_INTERPRETED_REGEXP
ExternalReference ExternalReference::re_check_stack_guard_state(
Isolate* isolate) {
Address function;
#if V8_TARGET_ARCH_X64
function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
#elif V8_TARGET_ARCH_IA32
function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
#elif V8_TARGET_ARCH_ARM64
function = FUNCTION_ADDR(RegExpMacroAssemblerARM64::CheckStackGuardState);
#elif V8_TARGET_ARCH_ARM
function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
#elif V8_TARGET_ARCH_PPC
function = FUNCTION_ADDR(RegExpMacroAssemblerPPC::CheckStackGuardState);
#elif V8_TARGET_ARCH_MIPS
function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
#elif V8_TARGET_ARCH_MIPS64
function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
#elif V8_TARGET_ARCH_S390
function = FUNCTION_ADDR(RegExpMacroAssemblerS390::CheckStackGuardState);
#else
UNREACHABLE();
#endif
return ExternalReference(Redirect(function));
}
ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
return ExternalReference(
Redirect(FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
}
ExternalReference ExternalReference::re_case_insensitive_compare_uc16(
Isolate* isolate) {
return ExternalReference(Redirect(
FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
}
ExternalReference ExternalReference::re_word_character_map(Isolate* isolate) {
return ExternalReference(
NativeRegExpMacroAssembler::word_character_map_address());
}
ExternalReference ExternalReference::address_of_static_offsets_vector(
Isolate* isolate) {
return ExternalReference(
reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector()));
}
ExternalReference ExternalReference::address_of_regexp_stack_limit(
Isolate* isolate) {
return ExternalReference(isolate->regexp_stack()->limit_address());
}
ExternalReference ExternalReference::address_of_regexp_stack_memory_address(
Isolate* isolate) {
return ExternalReference(isolate->regexp_stack()->memory_address());
}
ExternalReference ExternalReference::address_of_regexp_stack_memory_size(
Isolate* isolate) {
return ExternalReference(isolate->regexp_stack()->memory_size_address());
}
#endif // V8_INTERPRETED_REGEXP
ExternalReference ExternalReference::ieee754_acos_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::acos), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_acosh_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::acosh), BUILTIN_FP_FP_CALL));
}
ExternalReference ExternalReference::ieee754_asin_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::asin), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_asinh_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::asinh), BUILTIN_FP_FP_CALL));
}
ExternalReference ExternalReference::ieee754_atan_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::atan), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_atanh_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::atanh), BUILTIN_FP_FP_CALL));
}
ExternalReference ExternalReference::ieee754_atan2_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::atan2), BUILTIN_FP_FP_CALL));
}
ExternalReference ExternalReference::ieee754_cbrt_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::cbrt), BUILTIN_FP_FP_CALL));
}
ExternalReference ExternalReference::ieee754_cos_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::cos), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_cosh_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::cosh), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_exp_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::exp), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_expm1_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::expm1), BUILTIN_FP_FP_CALL));
}
ExternalReference ExternalReference::ieee754_log_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::log), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_log1p_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::log1p), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_log10_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::log10), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_log2_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::log2), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_sin_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::sin), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_sinh_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::sinh), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_tan_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::tan), BUILTIN_FP_CALL));
}
ExternalReference ExternalReference::ieee754_tanh_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(base::ieee754::tanh), BUILTIN_FP_CALL));
}
void* libc_memchr(void* string, int character, size_t search_length) {
return memchr(string, character, search_length);
}
ExternalReference ExternalReference::libc_memchr_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(libc_memchr)));
}
void* libc_memcpy(void* dest, const void* src, size_t n) {
return memcpy(dest, src, n);
}
ExternalReference ExternalReference::libc_memcpy_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(libc_memcpy)));
}
void* libc_memmove(void* dest, const void* src, size_t n) {
return memmove(dest, src, n);
}
ExternalReference ExternalReference::libc_memmove_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(libc_memmove)));
}
void* libc_memset(void* dest, int byte, size_t n) {
DCHECK_EQ(static_cast<char>(byte), byte);
return memset(dest, byte, n);
}
ExternalReference ExternalReference::libc_memset_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(libc_memset)));
}
ExternalReference ExternalReference::printf_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(std::printf)));
}
template <typename SubjectChar, typename PatternChar>
ExternalReference ExternalReference::search_string_raw() {
auto f = SearchStringRaw<SubjectChar, PatternChar>;
return ExternalReference(Redirect(FUNCTION_ADDR(f)));
}
ExternalReference ExternalReference::search_string_raw_one_one() {
return search_string_raw<const uint8_t, const uint8_t>();
}
ExternalReference ExternalReference::search_string_raw_one_two() {
return search_string_raw<const uint8_t, const uc16>();
}
ExternalReference ExternalReference::search_string_raw_two_one() {
return search_string_raw<const uc16, const uint8_t>();
}
ExternalReference ExternalReference::search_string_raw_two_two() {
return search_string_raw<const uc16, const uc16>();
}
ExternalReference ExternalReference::orderedhashmap_gethash_raw() {
auto f = OrderedHashMap::GetHash;
return ExternalReference(Redirect(FUNCTION_ADDR(f)));
}
ExternalReference ExternalReference::get_or_create_hash_raw(Isolate* isolate) {
typedef Smi* (*GetOrCreateHash)(Isolate * isolate, Object * key);
GetOrCreateHash f = Object::GetOrCreateHash;
return ExternalReference(Redirect(FUNCTION_ADDR(f)));
}
ExternalReference ExternalReference::jsreceiver_create_identity_hash(
Isolate* isolate) {
typedef Smi* (*CreateIdentityHash)(Isolate * isolate, JSReceiver * key);
CreateIdentityHash f = JSReceiver::CreateIdentityHash;
return ExternalReference(Redirect(FUNCTION_ADDR(f)));
}
ExternalReference
ExternalReference::copy_fast_number_jsarray_elements_to_typed_array() {
return ExternalReference(
Redirect(FUNCTION_ADDR(CopyFastNumberJSArrayElementsToTypedArray)));
}
ExternalReference
ExternalReference::copy_typed_array_elements_to_typed_array() {
return ExternalReference(
Redirect(FUNCTION_ADDR(CopyTypedArrayElementsToTypedArray)));
}
ExternalReference ExternalReference::copy_typed_array_elements_slice() {
return ExternalReference(
Redirect(FUNCTION_ADDR(CopyTypedArrayElementsSlice)));
}
ExternalReference ExternalReference::try_internalize_string_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(StringTable::LookupStringIfExists_NoAllocate)));
}
ExternalReference ExternalReference::check_object_type() {
return ExternalReference(Redirect(FUNCTION_ADDR(CheckObjectType)));
}
#ifdef V8_INTL_SUPPORT
ExternalReference ExternalReference::intl_convert_one_byte_to_lower() {
return ExternalReference(Redirect(FUNCTION_ADDR(ConvertOneByteToLower)));
}
ExternalReference ExternalReference::intl_to_latin1_lower_table() {
uint8_t* ptr = const_cast<uint8_t*>(ToLatin1LowerTable());
return ExternalReference(reinterpret_cast<Address>(ptr));
}
#endif // V8_INTL_SUPPORT
// Explicit instantiations for all combinations of 1- and 2-byte strings.
template ExternalReference
ExternalReference::search_string_raw<const uint8_t, const uint8_t>();
template ExternalReference
ExternalReference::search_string_raw<const uint8_t, const uc16>();
template ExternalReference
ExternalReference::search_string_raw<const uc16, const uint8_t>();
template ExternalReference
ExternalReference::search_string_raw<const uc16, const uc16>();
ExternalReference ExternalReference::page_flags(Page* page) {
return ExternalReference(reinterpret_cast<Address>(page) +
MemoryChunk::kFlagsOffset);
}
ExternalReference ExternalReference::ForDeoptEntry(Address entry) {
return ExternalReference(entry);
}
ExternalReference ExternalReference::cpu_features() {
DCHECK(CpuFeatures::initialized_);
return ExternalReference(&CpuFeatures::supported_);
}
ExternalReference ExternalReference::promise_hook_address(Isolate* isolate) {
return ExternalReference(isolate->promise_hook_address());
}
ExternalReference ExternalReference::async_event_delegate_address(
Isolate* isolate) {
return ExternalReference(isolate->async_event_delegate_address());
}
ExternalReference
ExternalReference::promise_hook_or_async_event_delegate_address(
Isolate* isolate) {
return ExternalReference(
isolate->promise_hook_or_async_event_delegate_address());
}
ExternalReference ExternalReference::debug_is_active_address(Isolate* isolate) {
return ExternalReference(isolate->debug()->is_active_address());
}
ExternalReference ExternalReference::debug_hook_on_function_call_address(
Isolate* isolate) {
return ExternalReference(isolate->debug()->hook_on_function_call_address());
}
ExternalReference ExternalReference::debug_execution_mode_address(
Isolate* isolate) {
return ExternalReference(isolate->debug_execution_mode_address());
}
ExternalReference ExternalReference::runtime_function_table_address(
Isolate* isolate) {
return ExternalReference(
const_cast<Runtime::Function*>(Runtime::RuntimeFunctionTable(isolate)));
}
ExternalReference ExternalReference::invalidate_prototype_chains_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(JSObject::InvalidatePrototypeChains)));
}
double power_helper(Isolate* isolate, double x, double y) {
int y_int = static_cast<int>(y);
if (y == y_int) {
return power_double_int(x, y_int); // Returns 1 if exponent is 0.
}
if (y == 0.5) {
lazily_initialize_fast_sqrt(isolate);
return (std::isinf(x)) ? V8_INFINITY
: fast_sqrt(x + 0.0, isolate); // Convert -0 to +0.
}
if (y == -0.5) {
lazily_initialize_fast_sqrt(isolate);
return (std::isinf(x)) ? 0
: 1.0 / fast_sqrt(x + 0.0,
isolate); // Convert -0 to +0.
}
return power_double_double(x, y);
}
// Helper function to compute x^y, where y is known to be an
// integer. Uses binary decomposition to limit the number of
// multiplications; see the discussion in "Hacker's Delight" by Henry
// S. Warren, Jr., figure 11-6, page 213.
double power_double_int(double x, int y) {
double m = (y < 0) ? 1 / x : x;
unsigned n = (y < 0) ? -y : y;
double p = 1;
while (n != 0) {
if ((n & 1) != 0) p *= m;
m *= m;
if ((n & 2) != 0) p *= m;
m *= m;
n >>= 2;
}
return p;
}
double power_double_double(double x, double y) {
// The checks for special cases can be dropped in ia32 because it has already
// been done in generated code before bailing out here.
if (std::isnan(y) || ((x == 1 || x == -1) && std::isinf(y))) {
return std::numeric_limits<double>::quiet_NaN();
}
return Pow(x, y);
}
double modulo_double_double(double x, double y) { return Modulo(x, y); }
ExternalReference ExternalReference::power_double_double_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(power_double_double), BUILTIN_FP_FP_CALL));
}
ExternalReference ExternalReference::mod_two_doubles_operation() {
return ExternalReference(
Redirect(FUNCTION_ADDR(modulo_double_double), BUILTIN_FP_FP_CALL));
}
ExternalReference ExternalReference::debug_last_step_action_address(
Isolate* isolate) {
return ExternalReference(isolate->debug()->last_step_action_address());
}
ExternalReference ExternalReference::debug_suspended_generator_address(
Isolate* isolate) {
return ExternalReference(isolate->debug()->suspended_generator_address());
}
ExternalReference ExternalReference::debug_restart_fp_address(
Isolate* isolate) {
return ExternalReference(isolate->debug()->restart_fp_address());
}
ExternalReference ExternalReference::fixed_typed_array_base_data_offset() {
return ExternalReference(reinterpret_cast<void*>(
FixedTypedArrayBase::kDataOffset - kHeapObjectTag));
}
bool operator==(ExternalReference lhs, ExternalReference rhs) {
return lhs.address() == rhs.address();
}
bool operator!=(ExternalReference lhs, ExternalReference rhs) {
return !(lhs == rhs);
}
size_t hash_value(ExternalReference reference) {
return base::hash<Address>()(reference.address());
}
std::ostream& operator<<(std::ostream& os, ExternalReference reference) {
os << reinterpret_cast<const void*>(reference.address());
const Runtime::Function* fn = Runtime::FunctionForEntry(reference.address());
if (fn) os << "<" << fn->name << ".entry>";
return os;
}
} // namespace internal
} // namespace v8