Commit 7e8a197c authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

Port bitfield ScopeFlags to Torque

In the process:

* Rework the Torque definition of ScopeInfo to enable direct
  field-style access of ScopeFlags, removing some dead code in
  the process.
* Allow implicit FromConstexpr conversion from subtypes of
  'constexpr A' to other types. This makes it possible/easy to
  convert constexpr versions of enums to other types, since the
  constexpr version of the enum isn't addressable. It's namespace
  isn't a valid namespace and is an implementation detail anyway.
* Cleanup LanguageMode: Language mode is now an enum and directly
  mirrors the C++-side definition rather than being a Smi. With
  the changes above, a new type LanguageModeSmi is introduced
  that is the Smi representation of LanguageMode that can be
  implicitly casted from constexpr LanguageMode values.

Change-Id: I190412f95e02905f445d149883fbf1f2b8ed757b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1977159
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65561}
parent 5ba9362b
......@@ -1085,6 +1085,7 @@ torque_files = [
"src/objects/property-cell.tq",
"src/objects/prototype-info.tq",
"src/objects/regexp-match-info.tq",
"src/objects/scope-info.tq",
"src/objects/script.tq",
"src/objects/shared-function-info.tq",
"src/objects/source-text-module.tq",
......@@ -1185,6 +1186,7 @@ v8_source_set("torque_generated_initializers") {
"$target_gen_dir/torque-generated/enum-verifiers-tq.cc",
"$target_gen_dir/torque-generated/exported-macros-assembler-tq.cc",
"$target_gen_dir/torque-generated/exported-macros-assembler-tq.h",
"src/torque/runtime-support.h",
]
foreach(file, torque_files) {
filetq = string_replace(file, ".tq", "-tq-csa")
......
......@@ -33,7 +33,7 @@ class Variable final : public ZoneObject {
InitializationFlagField::encode(initialization_flag) |
VariableModeField::encode(mode) |
IsUsedField::encode(false) |
ForceContextAllocationField::encode(false) |
ForceContextAllocationBit::encode(false) |
ForceHoleInitializationField::encode(false) |
LocationField::encode(VariableLocation::UNALLOCATED) |
VariableKindField::encode(kind) |
......@@ -72,12 +72,12 @@ class Variable final : public ZoneObject {
bool is_static() const { return is_static_flag() == IsStaticFlag::kStatic; }
bool has_forced_context_allocation() const {
return ForceContextAllocationField::decode(bit_field_);
return ForceContextAllocationBit::decode(bit_field_);
}
void ForceContextAllocation() {
DCHECK(IsUnallocated() || IsContextSlot() || IsLookupSlot() ||
location() == VariableLocation::MODULE);
bit_field_ = ForceContextAllocationField::update(bit_field_, true);
bit_field_ = ForceContextAllocationBit::update(bit_field_, true);
}
bool is_used() { return IsUsedField::decode(bit_field_); }
void set_is_used() { bit_field_ = IsUsedField::update(bit_field_, true); }
......@@ -264,8 +264,8 @@ class Variable final : public ZoneObject {
using VariableModeField = base::BitField16<VariableMode, 0, 4>;
using VariableKindField = VariableModeField::Next<VariableKind, 3>;
using LocationField = VariableKindField::Next<VariableLocation, 3>;
using ForceContextAllocationField = LocationField::Next<bool, 1>;
using IsUsedField = ForceContextAllocationField::Next<bool, 1>;
using ForceContextAllocationBit = LocationField::Next<bool, 1>;
using IsUsedField = ForceContextAllocationBit::Next<bool, 1>;
using InitializationFlagField = IsUsedField::Next<InitializationFlag, 1>;
using ForceHoleInitializationField = InitializationFlagField::Next<bool, 1>;
using MaybeAssignedFlagField =
......
......@@ -20,6 +20,7 @@
#include 'src/objects/stack-frame-info.h'
#include 'src/objects/synthetic-module.h'
#include 'src/objects/template-objects.h'
#include 'src/torque/runtime-support.h'
type void;
type never;
......@@ -138,12 +139,6 @@ type InstanceType extends uint16 constexpr 'v8::internal::InstanceType';
type NoSharedNameSentinel extends Smi;
extern class ScopeInfo extends FixedArray;
operator '[]' macro LoadScopeInfoElement(s: ScopeInfo, i: intptr): Object {
return s.objects[i];
}
// Specialized types. The following three type definitions don't correspond to
// actual C++ classes, but have Is... methods that check additional constraints.
......@@ -335,9 +330,6 @@ extern enum PrimitiveType { kString, kBoolean, kSymbol, kNumber }
const kNameDictionaryInitialCapacity:
constexpr int32 generates 'NameDictionary::kInitialCapacity';
const kScopeInfoFlagsIndex:
constexpr int32 generates 'ScopeInfo::Fields::kFlags';
type TheHole extends Oddball;
type Null extends Oddball;
type Undefined extends Oddball;
......@@ -374,7 +366,8 @@ const kZero: Zero = %RawDownCast<Zero>(SmiConstant(0));
const true: constexpr bool generates 'true';
const false: constexpr bool generates 'false';
extern enum LanguageMode extends Smi { kStrict, kSloppy }
extern enum LanguageMode extends bool { kStrict, kSloppy }
type LanguageModeSmi extends Smi;
const SKIP_WRITE_BARRIER:
constexpr WriteBarrierMode generates 'SKIP_WRITE_BARRIER';
......@@ -433,7 +426,7 @@ extern transitioning builtin SetProperty(implicit context: Context)(
extern transitioning builtin SetPropertyInLiteral(implicit context: Context)(
JSAny, JSAny, JSAny);
extern transitioning builtin DeleteProperty(implicit context: Context)(
JSAny, JSAny | PrivateSymbol, LanguageMode): Boolean;
JSAny, JSAny | PrivateSymbol, LanguageModeSmi): Boolean;
extern transitioning builtin HasProperty(implicit context: Context)(
JSAny, JSAny): Boolean;
extern transitioning macro HasProperty_Inline(implicit context: Context)(
......@@ -836,6 +829,8 @@ extern macro Float64Constant(constexpr float64): float64;
extern macro SmiConstant(constexpr int31): Smi;
extern macro SmiConstant(constexpr Smi): Smi;
extern macro SmiConstant(constexpr MessageTemplate): Smi;
extern macro SmiConstant(constexpr bool): Smi;
extern macro SmiConstant(constexpr uint32): Smi;
extern macro BoolConstant(constexpr bool): bool;
extern macro StringConstant(constexpr string): String;
extern macro IntPtrConstant(constexpr ContextSlot): ContextSlot;
......
......@@ -86,6 +86,10 @@ FromConstexpr<ContextSlot, constexpr ContextSlot>(c: constexpr ContextSlot):
ContextSlot {
return IntPtrConstant(c);
}
FromConstexpr<LanguageModeSmi, constexpr LanguageMode>(
c: constexpr LanguageMode): LanguageModeSmi {
return %RawDownCast<LanguageModeSmi>(SmiConstant(c));
}
macro Convert<To: type, From: type>(i: From): To {
return i;
......@@ -251,3 +255,6 @@ Convert<Smi, bint>(v: bint): Smi {
Convert<PromiseState, int32>(s: int32): PromiseState {
return %RawDownCast<PromiseState>(s);
}
Convert<ScopeFlags, Smi>(s: Smi): ScopeFlags {
return %RawDownCast<ScopeFlags>(Unsigned(SmiToInt32(s)));
}
......@@ -10,7 +10,7 @@ namespace proxy {
// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-delete-p
transitioning builtin
ProxyDeleteProperty(implicit context: Context)(
proxy: JSProxy, name: PropertyKey, languageMode: LanguageMode): JSAny {
proxy: JSProxy, name: PropertyKey, languageMode: LanguageModeSmi): JSAny {
const kTrapName: constexpr string = 'deleteProperty';
// Handle deeply nested proxy.
PerformStackCheck();
......@@ -41,7 +41,8 @@ namespace proxy {
// 9. If booleanTrapResult is false, return false.
if (!ToBoolean(trapResult)) {
if (languageMode == SmiConstant(LanguageMode::kStrict)) {
const strictValue: LanguageModeSmi = LanguageMode::kStrict;
if (languageMode == strictValue) {
ThrowTypeError(
MessageTemplate::kProxyTrapReturnedFalsishFor, kTrapName, name);
}
......
......@@ -2656,7 +2656,7 @@ TNode<BoolT> CodeStubAssembler::LoadScopeInfoHasExtensionField(
TNode<ScopeInfo> scope_info) {
TNode<IntPtrT> value =
LoadAndUntagObjectField(scope_info, ScopeInfo::kFlagsOffset);
return IsSetWord<ScopeInfo::HasContextExtensionSlotField>(value);
return IsSetWord<ScopeInfo::HasContextExtensionSlotBit>(value);
}
TNode<Object> CodeStubAssembler::LoadContextElement(
......@@ -13341,10 +13341,5 @@ void PrototypeCheckAssembler::CheckAndBranch(TNode<HeapObject> prototype,
}
}
TNode<IntPtrT> CodeStubAssembler::DecodeScopeInfoHasContextExtension(
TNode<IntPtrT> flags) {
return Signed(DecodeWord<ScopeInfo::HasContextExtensionSlotField>(flags));
}
} // namespace internal
} // namespace v8
......@@ -2745,8 +2745,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word, uint32_t shift,
uint32_t mask);
TNode<IntPtrT> DecodeScopeInfoHasContextExtension(TNode<IntPtrT> flags);
// Returns a node that contains the updated values of a |BitField|.
template <typename BitField>
TNode<Word32T> UpdateWord32(TNode<Word32T> word, TNode<Uint32T> value) {
......
......@@ -1629,6 +1629,11 @@ V8_INLINE bool operator!(ExceptionStatus status) {
enum class TraceRetainingPathMode { kEnabled, kDisabled };
// Used in the ScopeInfo flags fields for the function name variable for named
// function expressions, and for the receiver. Must be declared here so that it
// can be used in Torque.
enum class VariableAllocationInfo { NONE, STACK, CONTEXT, UNUSED };
} // namespace internal
} // namespace v8
......
......@@ -3547,7 +3547,7 @@ int ScopeInfoRef::Flags() const {
}
bool ScopeInfoRef::HasContextExtension() const {
return ScopeInfo::HasContextExtensionSlotField::decode(Flags());
return ScopeInfo::HasContextExtensionSlotBit::decode(Flags());
}
bool ScopeInfoRef::HasOuterScopeInfo() const {
......
......@@ -1334,7 +1334,7 @@ Reduction JSTypedLowering::ReduceJSHasContextExtension(Node* node) {
effect, control);
Node* flags_masked = graph()->NewNode(
simplified()->NumberBitwiseAnd(), scope_info_flags,
jsgraph()->SmiConstant(ScopeInfo::HasContextExtensionSlotField::kMask));
jsgraph()->SmiConstant(ScopeInfo::HasContextExtensionSlotBit::kMask));
Node* no_extension = graph()->NewNode(
simplified()->NumberEqual(), flags_masked, jsgraph()->SmiConstant(0));
Node* has_extension =
......
......@@ -2142,14 +2142,13 @@ void ScopeInfo::ScopeInfoPrint(std::ostream& os) { // NOLINT
os << "\n - language mode: " << language_mode();
if (is_declaration_scope()) os << "\n - declaration scope";
if (HasReceiver()) {
os << "\n - receiver: " << ReceiverVariableField::decode(flags);
os << "\n - receiver: " << ReceiverVariableBits::decode(flags);
}
if (HasClassBrand()) os << "\n - has class brand";
if (HasSavedClassVariableIndex()) os << "\n - has saved class variable index";
if (HasNewTarget()) os << "\n - needs new target";
if (HasFunctionName()) {
os << "\n - function name(" << FunctionVariableField::decode(flags)
<< "): ";
os << "\n - function name(" << FunctionVariableBits::decode(flags) << "): ";
FunctionName().ShortPrint(os);
}
if (IsAsmModule()) os << "\n - asm module";
......
......@@ -97,11 +97,9 @@ namespace arguments {
macro NewParameterMapIterator(
context: Context, elements: FixedArray, formalParameterCount: intptr,
mappedCount: intptr): ParameterMapIterator {
const scopeInfoFlags = Convert<intptr>(
UnsafeCast<Smi>(context.scope_info[kScopeInfoFlagsIndex]));
const contextExtentionSize =
DecodeScopeInfoHasContextExtension(scopeInfoFlags);
const contextHeaderSize = MIN_CONTEXT_SLOTS + contextExtentionSize;
const flags = context.scope_info.flags;
let contextHeaderSize: intptr = MIN_CONTEXT_SLOTS;
if (flags.has_context_extension_slot) ++contextHeaderSize;
// Copy the parameter slots and the holes in the arguments.
// We need to fill in mapped_count slots. They index the context,
// where parameters are stored in reverse order, at
......
......@@ -1097,12 +1097,10 @@ static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key,
PACKED_ELEMENTS, 2);
}
bool ScopeInfo::IsAsmModule() const {
return IsAsmModuleField::decode(Flags());
}
bool ScopeInfo::IsAsmModule() const { return IsAsmModuleBit::decode(Flags()); }
bool ScopeInfo::HasSimpleParameters() const {
return HasSimpleParametersField::decode(Flags());
return HasSimpleParametersBit::decode(Flags());
}
#define FIELD_ACCESSORS(name) \
......
This diff is collapsed.
......@@ -11,6 +11,7 @@
#include "src/objects/objects.h"
#include "src/utils/utils.h"
#include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck
#include "torque-generated/bit-fields-tq.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......@@ -35,7 +36,7 @@ class Zone;
// This object provides quick access to scope info details for runtime
// routines.
class ScopeInfo : public FixedArray {
class ScopeInfo : public FixedArray, public TorqueGeneratedScopeFlagsFields {
public:
DECL_CAST(ScopeInfo)
DECL_PRINTER(ScopeInfo)
......@@ -260,40 +261,8 @@ class ScopeInfo : public FixedArray {
static const int kFlagsOffset = OffsetOfElementAt(Fields::kFlags);
// Used for the function name variable for named function expressions, and for
// the receiver.
enum VariableAllocationInfo { NONE, STACK, CONTEXT, UNUSED };
// Properties of scopes.
using ScopeTypeField = base::BitField<ScopeType, 0, 4>;
using SloppyEvalCanExtendVarsField = ScopeTypeField::Next<bool, 1>;
STATIC_ASSERT(LanguageModeSize == 2);
using LanguageModeField = SloppyEvalCanExtendVarsField::Next<LanguageMode, 1>;
using DeclarationScopeField = LanguageModeField::Next<bool, 1>;
using ReceiverVariableField =
DeclarationScopeField::Next<VariableAllocationInfo, 2>;
using HasClassBrandField = ReceiverVariableField::Next<bool, 1>;
using HasSavedClassVariableIndexField = HasClassBrandField::Next<bool, 1>;
using HasNewTargetField = HasSavedClassVariableIndexField::Next<bool, 1>;
using FunctionVariableField =
HasNewTargetField::Next<VariableAllocationInfo, 2>;
// TODO(cbruni): Combine with function variable field when only storing the
// function name.
using HasInferredFunctionNameField = FunctionVariableField::Next<bool, 1>;
using IsAsmModuleField = HasInferredFunctionNameField::Next<bool, 1>;
using HasSimpleParametersField = IsAsmModuleField::Next<bool, 1>;
using FunctionKindField = HasSimpleParametersField::Next<FunctionKind, 5>;
using HasOuterScopeInfoField = FunctionKindField::Next<bool, 1>;
using IsDebugEvaluateScopeField = HasOuterScopeInfoField::Next<bool, 1>;
using ForceContextAllocationField = IsDebugEvaluateScopeField::Next<bool, 1>;
using PrivateNameLookupSkipsOuterClassField =
ForceContextAllocationField::Next<bool, 1>;
using HasContextExtensionSlotField =
PrivateNameLookupSkipsOuterClassField::Next<bool, 1>;
using IsReplModeScopeField = HasContextExtensionSlotField::Next<bool, 1>;
using HasLocalsBlackListField = IsReplModeScopeField::Next<bool, 1>;
STATIC_ASSERT(kLastFunctionKind <= FunctionKindField::kMax);
STATIC_ASSERT(LanguageModeSize == 1 << LanguageModeBit::kSize);
STATIC_ASSERT(kLastFunctionKind <= FunctionKindBits::kMax);
private:
// The layout of the variable part of a ScopeInfo is as follows:
......@@ -376,15 +345,13 @@ class ScopeInfo : public FixedArray {
using IsStaticFlagField = ParameterNumberField::Next<IsStaticFlag, 1>;
friend class ScopeIterator;
friend std::ostream& operator<<(std::ostream& os,
ScopeInfo::VariableAllocationInfo var);
friend std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var);
OBJECT_CONSTRUCTORS(ScopeInfo, FixedArray);
FRIEND_TEST(TestWithNativeContext, RecreateScopeInfoWithLocalsBlacklistWorks);
};
std::ostream& operator<<(std::ostream& os,
ScopeInfo::VariableAllocationInfo var);
std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var);
} // namespace internal
} // namespace v8
......
// Copyright 2019 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.
extern class ScopeInfo extends FixedArray;
const kScopeInfoFlagsIndex:
constexpr int32 generates 'ScopeInfo::Fields::kFlags';
operator '.flags' macro LoadScopeInfoFlags(implicit context: Context)(
scopeInfo: ScopeInfo): ScopeFlags {
return Convert<ScopeFlags>(
UnsafeCast<Smi>(scopeInfo.objects[kScopeInfoFlagsIndex]));
}
type ScopeType extends uint32 constexpr 'ScopeType';
type VariableAllocationInfo extends uint32
constexpr 'VariableAllocationInfo';
// Properties of scopes.
bitfield struct ScopeFlags extends uint32 {
scope_type: ScopeType: 4 bit;
sloppy_eval_can_extend_vars: bool: 1 bit;
language_mode: LanguageMode: 1 bit;
declaration_scope: bool: 1 bit;
receiver_variable: VariableAllocationInfo: 2 bit;
has_class_brand: bool: 1 bit;
has_saved_class_variable_index: bool: 1 bit;
has_new_target: bool: 1 bit;
// TODO(cbruni): Combine with function variable field when only storing the
// function name.
function_variable: VariableAllocationInfo: 2 bit;
has_inferred_function_name: bool: 1 bit;
is_asm_module: bool: 1 bit;
has_simple_parameters: bool: 1 bit;
function_kind: FunctionKind: 5 bit;
has_outer_scope_info: bool: 1 bit;
is_debug_evaluate_scope: bool: 1 bit;
force_context_allocation: bool: 1 bit;
private_name_lookup_skips_outer_class: bool: 1 bit;
has_context_extension_slot: bool: 1 bit;
is_repl_mode_scope: bool: 1 bit;
has_locals_black_list: bool: 1 bit;
}
......@@ -21,9 +21,8 @@ namespace internal {
namespace {
using ScopeSloppyEvalCanExtendVarsField = base::BitField8<bool, 0, 1>;
using InnerScopeCallsEvalField =
ScopeSloppyEvalCanExtendVarsField::Next<bool, 1>;
using ScopeSloppyEvalCanExtendVarsBit = base::BitField8<bool, 0, 1>;
using InnerScopeCallsEvalField = ScopeSloppyEvalCanExtendVarsBit::Next<bool, 1>;
using NeedsPrivateNameContextChainRecalcField =
InnerScopeCallsEvalField::Next<bool, 1>;
using ShouldSaveClassVariableIndexField =
......@@ -357,7 +356,7 @@ void PreparseDataBuilder::SaveDataForScope(Scope* scope) {
#endif
uint8_t eval_and_private_recalc =
ScopeSloppyEvalCanExtendVarsField::encode(
ScopeSloppyEvalCanExtendVarsBit::encode(
scope->is_declaration_scope() &&
scope->AsDeclarationScope()->sloppy_eval_can_extend_vars()) |
InnerScopeCallsEvalField::encode(scope->inner_scope_calls_eval()) |
......@@ -612,7 +611,7 @@ void BaseConsumedPreparseData<Data>::RestoreDataForScope(
CHECK(scope_data_->HasRemainingBytes(ByteData::kUint8Size));
uint32_t scope_data_flags = scope_data_->ReadUint8();
if (ScopeSloppyEvalCanExtendVarsField::decode(scope_data_flags)) {
if (ScopeSloppyEvalCanExtendVarsBit::decode(scope_data_flags)) {
scope->RecordEvalCall();
}
if (InnerScopeCallsEvalField::decode(scope_data_flags)) {
......
......@@ -241,11 +241,16 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
out_ << "ca_.UintPtrConstant";
} else if (return_type->IsSubtypeOf(TypeOracle::GetInt32Type())) {
out_ << "ca_.Int32Constant";
} else if (return_type->IsSubtypeOf(TypeOracle::GetBoolType())) {
out_ << "ca_.BoolConstant";
} else {
std::stringstream s;
s << "%FromConstexpr does not support return type " << *return_type;
ReportError(s.str());
}
// Wrap the raw constexpr value in a static_cast to ensure that
// enums get properly casted to their backing integral value.
out_ << "(CastToUnderlyingTypeIfEnum";
} else {
ReportError("no built in intrinsic with name " +
instruction.intrinsic->ExternalName());
......@@ -253,6 +258,9 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
out_ << "(";
PrintCommaSeparatedList(out_, args);
if (instruction.intrinsic->ExternalName() == "%FromConstexpr") {
out_ << ")";
}
if (return_type->IsStructType()) {
out_ << ").Flatten();\n";
} else {
......
......@@ -2692,11 +2692,11 @@ VisitResult ImplementationVisitor::GenerateImplicitConvert(
return scope.Yield(GenerateCopy(source));
}
if (TypeOracle::IsImplicitlyConvertableFrom(destination_type,
source.type())) {
if (auto from = TypeOracle::ImplicitlyConvertableFrom(destination_type,
source.type())) {
return scope.Yield(GenerateCall(kFromConstexprMacroName,
Arguments{{source}, {}},
{destination_type, source.type()}, false));
{destination_type, *from}, false));
} else if (IsAssignableFrom(destination_type, source.type())) {
source.SetType(destination_type);
return scope.Yield(GenerateCopy(source));
......
// Copyright 2019 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.
#ifndef V8_TORQUE_RUNTIME_SUPPORT_H_
#define V8_TORQUE_RUNTIME_SUPPORT_H_
#include <type_traits>
template <class T>
struct Identity {
using type = T;
};
template <class T>
struct UnderlyingTypeHelper : Identity<typename std::underlying_type<T>::type> {
};
template <class T>
using UnderlyingTypeIfEnum =
typename std::conditional_t<std::is_enum<T>::value, UnderlyingTypeHelper<T>,
Identity<T>>::type;
// Utility for extracting the underlying type of an enum, returns the type
// itself if not an enum.
template <class T>
UnderlyingTypeIfEnum<T> CastToUnderlyingTypeIfEnum(T x) {
return static_cast<UnderlyingTypeIfEnum<T>>(x);
}
#endif // V8_TORQUE_RUNTIME_SUPPORT_H_
......@@ -281,18 +281,22 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return Get().GetBuiltinType(UNINITIALIZED_ITERATOR_TYPE_STRING);
}
static bool IsImplicitlyConvertableFrom(const Type* to, const Type* from) {
for (GenericCallable* from_constexpr :
Declarations::LookupGeneric(kFromConstexprMacroName)) {
if (base::Optional<const Callable*> specialization =
from_constexpr->GetSpecialization({to, from})) {
if ((*specialization)->signature().GetExplicitTypes() ==
TypeVector{from}) {
return true;
static base::Optional<const Type*> ImplicitlyConvertableFrom(
const Type* to, const Type* from) {
while (from != nullptr) {
for (GenericCallable* from_constexpr :
Declarations::LookupGeneric(kFromConstexprMacroName)) {
if (base::Optional<const Callable*> specialization =
from_constexpr->GetSpecialization({to, from})) {
if ((*specialization)->signature().GetExplicitTypes() ==
TypeVector{from}) {
return from;
}
}
}
from = from->parent();
}
return false;
return base::nullopt;
}
static const std::vector<std::unique_ptr<AggregateType>>& GetAggregateTypes();
......
......@@ -170,7 +170,7 @@ const BitFieldStructType* TypeVisitor::ComputeType(
// type. Booleans are a special case, not included in SizeOf, because their
// runtime size is 32 bits but they should only occupy 1 bit as a bitfield.
size_t field_type_size = 0;
if (field_type == TypeOracle::GetBoolType()) {
if (field_type->IsSubtypeOf(TypeOracle::GetBoolType())) {
field_type_size = 1;
} else {
auto opt_field_type_size = SizeOf(field_type);
......
......@@ -648,7 +648,7 @@ bool Signature::HasSameTypesAs(const Signature& other,
bool IsAssignableFrom(const Type* to, const Type* from) {
if (to == from) return true;
if (from->IsSubtypeOf(to)) return true;
return TypeOracle::IsImplicitlyConvertableFrom(to, from);
return TypeOracle::ImplicitlyConvertableFrom(to, from).has_value();
}
bool operator<(const Type& a, const Type& b) { return a.id() < b.id(); }
......
......@@ -113,6 +113,7 @@ class V8_EXPORT_PRIVATE Type : public TypeBase {
// Used for naming generated code.
virtual std::string SimpleName() const;
const Type* parent() const { return parent_; }
bool IsVoid() const { return IsAbstractName(VOID_TYPE_STRING); }
bool IsNever() const { return IsAbstractName(NEVER_TYPE_STRING); }
bool IsBool() const { return IsAbstractName(BOOL_TYPE_STRING); }
......@@ -160,7 +161,6 @@ class V8_EXPORT_PRIVATE Type : public TypeBase {
MaybeSpecializationKey specialized_from = base::nullopt);
Type(const Type& other) V8_NOEXCEPT;
Type& operator=(const Type& other) = delete;
const Type* parent() const { return parent_; }
void set_parent(const Type* t) { parent_ = t; }
int Depth() const;
virtual std::string ToExplicitString() const = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment