dart-sdk/runtime/vm/constants.h
Martin Kustermann b85679eaf3 [vm] Avoid runtime call in common type literal "T" case
Right now all type literal usages will perform a runtime call which is
rather slow.

Flutter happens to use type literals such as `return T;` in hot code
which causes this to show up in the profile.

This CL adds fast paths for type parameter type literals if
the type parameter value (i.e. entry of TAV corresponding to T):

    * is `null`: return `dynamic`
    * is a non-FutureOr [Type] with compatible nullability: return value
    * is [FunctionType] with compatible nullability: return value

otherwise fall back to runtime call.

It makes simple type literal uses 10x+ faster - the kinds that Flutter
is using.

Issue https://github.com/dart-lang/sdk/issues/48757

TEST=vm/dart{,_2}/instantiate_type_literal_test

Change-Id: I1139d6689aedbc68321f47ee6c9946a3323fbf6e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241968
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
2022-04-27 10:26:25 +00:00

85 lines
2.7 KiB
C++

// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_CONSTANTS_H_
#define RUNTIME_VM_CONSTANTS_H_
#if defined(TARGET_ARCH_IA32)
#include "vm/constants_ia32.h"
#elif defined(TARGET_ARCH_X64)
#include "vm/constants_x64.h"
#elif defined(TARGET_ARCH_ARM)
#include "vm/constants_arm.h"
#elif defined(TARGET_ARCH_ARM64)
#include "vm/constants_arm64.h"
#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
#include "vm/constants_riscv.h"
#else
#error Unknown architecture.
#endif
namespace dart {
// An architecture independent ABI for the InstantiateType stub.
//
// We re-use registers from another ABI to avoid duplicating this ABI across 4
// architectures.
struct InstantiateTypeABI {
static constexpr Register kTypeReg =
InstantiationABI::kUninstantiatedTypeArgumentsReg;
static constexpr Register kInstantiatorTypeArgumentsReg =
InstantiationABI::kInstantiatorTypeArgumentsReg;
static constexpr Register kFunctionTypeArgumentsReg =
InstantiationABI::kFunctionTypeArgumentsReg;
static constexpr Register kResultTypeReg = InstantiationABI::kResultTypeReg;
static constexpr Register kScratchReg = InstantiationABI::kScratchReg;
};
class RegisterNames {
public:
static const char* RegisterName(Register reg) {
ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters));
return cpu_reg_names[reg];
}
static const char* RegisterAbiName(Register reg) {
ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters));
return cpu_reg_abi_names[reg];
}
static const char* FpuRegisterName(FpuRegister reg) {
ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
return fpu_reg_names[reg];
}
#if defined(TARGET_ARCH_ARM)
static const char* FpuSRegisterName(SRegister reg) {
ASSERT((0 <= reg) && (reg < kNumberOfSRegisters));
return fpu_s_reg_names[reg];
}
static const char* FpuDRegisterName(DRegister reg) {
ASSERT((0 <= reg) && (reg < kNumberOfDRegisters));
return fpu_d_reg_names[reg];
}
#endif // defined(TARGET_ARCH_ARM)
};
static constexpr bool IsArgumentRegister(Register reg) {
return ((1 << reg) & CallingConventions::kArgumentRegisters) != 0;
}
static constexpr bool IsFpuArgumentRegister(FpuRegister reg) {
return ((1 << reg) & CallingConventions::kFpuArgumentRegisters) != 0;
}
static constexpr bool IsCalleeSavedRegister(Register reg) {
return ((1 << reg) & CallingConventions::kCalleeSaveCpuRegisters) != 0;
}
#if !defined(TARGET_ARCH_IA32)
constexpr bool IsAbiPreservedRegister(Register reg) {
return (kAbiPreservedCpuRegs & (1 << reg)) != 0;
}
#endif
} // namespace dart
#endif // RUNTIME_VM_CONSTANTS_H_