// Copyright (c) 2025, 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.

import 'vm_offsets.g.dart';
export 'vm_offsets.g.dart';

const int smiBit = 0;
const int heapObjectTag = 1;
const int smiShift = 1;

int objectAlignment(int wordSize) => wordSize * 2;
int log2objectAlignment(int log2wordSize) => log2wordSize + 1;

/// This bit is 0 for bool 'true', 1 for bool 'false'.
int boolValueBitPosition(int log2wordSize) => log2objectAlignment(log2wordSize);

/// The number of bits in the _magnitude_ of a Smi, not counting the sign bit.
int smiBits(int compressedWordSize) => (compressedWordSize * 8) - 2;

/// Predicates on predefined class ids.
extension ClassIdPredicates on ClassId {
  bool get isString => switch (this) {
    .StringCid || .OneByteStringCid || .TwoByteStringCid => true,
    _ => false,
  };

  bool get isUnmodifiableTypedDataView => switch (this) {
    .UnmodifiableTypedDataInt8ArrayViewCid ||
    .UnmodifiableTypedDataUint8ArrayViewCid ||
    .UnmodifiableTypedDataUint8ClampedArrayViewCid ||
    .UnmodifiableTypedDataInt16ArrayViewCid ||
    .UnmodifiableTypedDataUint16ArrayViewCid ||
    .UnmodifiableTypedDataInt32ArrayViewCid ||
    .UnmodifiableTypedDataUint32ArrayViewCid ||
    .UnmodifiableTypedDataInt64ArrayViewCid ||
    .UnmodifiableTypedDataUint64ArrayViewCid ||
    .UnmodifiableTypedDataFloat32ArrayViewCid ||
    .UnmodifiableTypedDataFloat64ArrayViewCid ||
    .UnmodifiableTypedDataFloat32x4ArrayViewCid ||
    .UnmodifiableTypedDataInt32x4ArrayViewCid ||
    .UnmodifiableTypedDataFloat64x2ArrayViewCid ||
    .UnmodifiableByteDataViewCid => true,
    _ => false,
  };

  bool get isShallowImmutable =>
      (this == .ClosureCid) || isUnmodifiableTypedDataView;

  bool get isDeeplyImmutable =>
      isString ||
      switch (this) {
        .NumberCid ||
        .IntegerCid ||
        .SmiCid ||
        .MintCid ||
        .NeverCid ||
        .SentinelCid ||
        .StackTraceCid ||
        .DoubleCid ||
        .Float32x4Cid ||
        .Float64x2Cid ||
        .Int32x4Cid ||
        .SendPortCid ||
        .CapabilityCid ||
        .RegExpCid ||
        .BoolCid ||
        .NullCid ||
        .PointerCid ||
        .TypeCid ||
        .TypeArgumentsCid ||
        .TypeParameterCid ||
        .RecordTypeCid ||
        .FunctionTypeCid ||
        .ConstMapCid => true,
        _ => false,
      };
}

extension ComputedOffsets on VMOffsets {
  /// Offset of [entry] in the Thread.
  // ignore: non_constant_identifier_names
  int Thread_runtime_entry_offset(RuntimeEntry entry, int wordSize) =>
      Thread_AllocateArray_entry_point_offset +
      (entry.index - RuntimeEntry.AllocateArray.index) * wordSize;

  /// Offset of [entry] in the Thread.
  // ignore: non_constant_identifier_names
  int Thread_leaf_runtime_entry_offset(LeafRuntimeEntry entry, int wordSize) =>
      Thread_DeoptimizeCopyFrame_entry_point_offset +
      (entry.index - LeafRuntimeEntry.DeoptimizeCopyFrame.index) * wordSize;

  /// Object tags for a freshly allocated object.
  int computeNewObjectTags(ClassId cid, int instanceSize, int log2wordSize) {
    final log2align = log2objectAlignment(log2wordSize);
    assert(instanceSize >= 0);
    assert((instanceSize & ((1 << log2align) - 1)) == 0);
    int encodedSize = instanceSize >> log2align;
    if (encodedSize >= (1 << UntaggedObject_kSizeTagSize)) {
      encodedSize = 0;
    }
    return (1 << UntaggedObject_kNewOrEvacuationCandidateBit) |
        (1 << UntaggedObject_kAlwaysSetBit) |
        (1 << UntaggedObject_kNotMarkedBit) |
        (cid.isShallowImmutable
            ? (1 << UntaggedObject_kShallowImmutableBit)
            : 0) |
        (cid.isDeeplyImmutable
            ? (1 << UntaggedObject_kDeeplyImmutableBit)
            : 0) |
        (encodedSize << UntaggedObject_kSizeTagPos) |
        (cid.index << UntaggedObject_kClassIdTagPos);
  }

  int encodeClosureLengthAndFlags(
    int numElements, {
    required bool hasDelayedTypeArgs,
    required bool hasInstantiatorTypeArgs,
    required bool hasFunctionTypeArgs,
  }) {
    assert(
      (0 <= numElements) &&
          (numElements < (1 << UntaggedClosure_kLengthBitsSize)),
    );
    final functionTypeArgsIndex =
        (hasDelayedTypeArgs ? 1 : 0) + (hasInstantiatorTypeArgs ? 1 : 0);
    assert(
      functionTypeArgsIndex <
          (1 << UntaggedClosure_kFunctionTypeArgumentsIndexBitsSize),
    );
    return (hasDelayedTypeArgs
            ? (1 << UntaggedClosure_kHasDelayedTypeArgumentsBit)
            : 0) |
        (hasInstantiatorTypeArgs
            ? (1 << UntaggedClosure_kHasInstantiatorTypeArgumentsBit)
            : 0) |
        (hasFunctionTypeArgs
            ? ((1 << UntaggedClosure_kHasFunctionTypeArgumentsBit) |
                  (functionTypeArgsIndex <<
                      UntaggedClosure_kFunctionTypeArgumentsIndexBitsPos))
            : 0) |
        (numElements << UntaggedClosure_kLengthBitsPos);
  }
}

// Symbol names used in Dart snapshots.

const String snapshotBuildIdAsmSymbol = "_kDartSnapshotBuildId";
const String vmSnapshotDataAsmSymbol = "_kDartVmSnapshotData";
const String vmSnapshotInstructionsAsmSymbol = "_kDartVmSnapshotInstructions";
const String vmSnapshotBssAsmSymbol = "_kDartVmSnapshotBss";
const String isolateSnapshotDataAsmSymbol = "_kDartIsolateSnapshotData";
const String isolateSnapshotInstructionsAsmSymbol =
    "_kDartIsolateSnapshotInstructions";
const String isolateSnapshotBssAsmSymbol = "_kDartIsolateSnapshotBss";
