blob: 3fb40ffeccb1e80966a80e2d8be1615e0fed4ca7 [file] [edit]
// Copyright (c) 2026, 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 'package:cfg/front_end/recognized_methods.dart';
import 'package:cfg/ir/constant_value.dart';
import 'package:cfg/ir/field.dart';
import 'package:cfg/ir/flow_graph_builder.dart';
import 'package:cfg/ir/functions.dart';
import 'package:cfg/ir/global_context.dart';
import 'package:cfg/ir/instructions.dart';
import 'package:cfg/ir/types.dart';
import 'package:kernel/ast.dart' as ast;
import 'package:kernel/external_name.dart' show getExternalName;
import 'package:native_compiler/runtime/constant_objects.dart';
import 'package:native_compiler/runtime/object_layout.dart';
import 'package:native_compiler/runtime/vm_defs.dart';
import 'package:vm/modular/transformations/pragma.dart';
/// Build IR for native methods.
void buildNativeMethod(
FlowGraphBuilder builder,
FunctionRegistry functionRegistry,
CFunction function,
) {
// Reserve extra argument slot for return value.
builder.addNullConstant();
final functionNode = function.functionNode!;
final argsShape = functionRegistry.getArgumentsShape(
(function.hasReceiverParameter ? 1 : 0) +
functionNode.positionalParameters.length +
1,
types: function.numberOfFunctionTypeParameters,
named: functionNode.namedParameters.map((p) => p.parameterName).toList(),
);
builder.addExternalCall(
function,
function.numberOfParameters + 1,
argsShape,
function.returnType,
);
}
/// Build IR for static getters returning constants.
void buildConstantGetter(FlowGraphBuilder builder, ConstantValue value) {
builder.addConstant(value);
}
/// Build IR for instance field getters.
void buildInstanceGetter(FlowGraphBuilder builder, CField field) {
builder.addLoadInstanceField(field, checkInitialized: field.isLate);
}
/// Build IR for instance field setters.
void buildInstanceSetter(FlowGraphBuilder builder, CField field) {
builder.addStoreInstanceField(
field,
checkNotInitialized: field.isLate && field.isFinal,
);
builder.addNullConstant();
}
/// Build IR for unary int operations
void buildUnaryIntOp(FlowGraphBuilder builder, UnaryIntOpcode op) {
builder.addUnaryIntOp(op);
}
/// Build IR for comparison operations
void buildComparisonOp(FlowGraphBuilder builder, ComparisonOpcode op) {
builder.addComparison(op);
}
/// Build IR for indexed load of an array element.
void buildArrayElementGetter(
FlowGraphBuilder builder,
ArrayKind kind,
CField lengthField,
CType elemType, {
CField? indirectDataField,
}) {
final index = builder.pop();
final array = builder.pop();
builder.push(array);
if (indirectDataField != null) {
builder.addLoadInstanceField(indirectDataField);
}
builder.push(index);
builder.push(array);
builder.addLoadInstanceField(lengthField);
builder.addIndexCheck();
builder.addLoadArrayElement(kind, elemType);
}
/// Build IR for indexed store to an array element.
void buildArrayElementSetter(
FlowGraphBuilder builder,
ArrayKind kind,
CField lengthField, {
CField? indirectDataField,
bool checkIndex = true,
}) {
final value = builder.pop();
final index = builder.pop();
final array = builder.pop();
builder.push(array);
if (indirectDataField != null) {
builder.addLoadInstanceField(indirectDataField);
}
builder.push(index);
if (checkIndex) {
builder.push(array);
builder.addLoadInstanceField(lengthField);
builder.addIndexCheck();
}
builder.push(value);
builder.addStoreArrayElement(kind);
builder.addNullConstant();
}
/// Build IR for factory constructors of typed data lists and built-in _List.
void buildArrayFactory(
FlowGraphBuilder builder,
ArrayKind kind,
ast.Class cls,
) {
final hasTypeArguments = kind == .fixedLengthList;
final coreTypes = GlobalContext.instance.coreTypes;
final type = switch (kind) {
.oneByteString ||
.twoByteString => StringType(coreTypes.nonNullableRawType(cls)),
_ => StaticType(
hasTypeArguments
? coreTypes.thisInterfaceType(cls, .nonNullable)
: coreTypes.nonNullableRawType(cls),
),
};
builder.addAllocateArray(kind, type, hasTypeArguments: hasTypeArguments);
}
void buildStringBaseCodeUnitAt(
FlowGraphBuilder builder,
ObjectLayout objectLayout,
) {
final index = builder.pop();
final string = builder.pop();
builder.push(index);
builder.push(string);
builder.addLoadInstanceField(objectLayout.StringBase_length);
builder.addIndexCheck();
final checkedIndex = builder.pop();
builder.push(string);
builder.addLoadInstanceField(objectLayout.Object_classId);
builder.addIntConstant(ClassId.OneByteStringCid.index);
builder.addComparison(.intEqual);
final oneByteStringBlock = builder.newTargetBlock();
final twoByteStringBlock = builder.newTargetBlock();
builder.addBranch(oneByteStringBlock, twoByteStringBlock);
final joinBlock = builder.newJoinBlock();
final resultVar = builder.declareLocalVariable(
'#result',
null,
const IntType(),
);
builder.startBlock(oneByteStringBlock);
builder.push(string);
builder.push(checkedIndex);
builder.addLoadArrayElement(.oneByteString, const IntType());
builder.addStoreLocal(resultVar);
builder.addGoto(joinBlock);
builder.startBlock(twoByteStringBlock);
builder.push(string);
builder.push(checkedIndex);
builder.addLoadArrayElement(.twoByteString, const IntType());
builder.addStoreLocal(resultVar);
builder.addGoto(joinBlock);
builder.startBlock(joinBlock);
builder.addLoadLocal(resultVar);
}
void buildStringBaseCharAt(
FlowGraphBuilder builder,
FunctionRegistry functionRegistry,
ObjectLayout objectLayout,
CFunction function,
) {
final index = builder.pop();
final string = builder.pop();
builder.push(index);
builder.push(string);
builder.addLoadInstanceField(objectLayout.StringBase_length);
builder.addIndexCheck();
final checkedIndex = builder.pop();
builder.push(string);
builder.addLoadInstanceField(objectLayout.Object_classId);
builder.addIntConstant(ClassId.OneByteStringCid.index);
builder.addComparison(.intEqual);
final oneByteStringBlock = builder.newTargetBlock();
final twoByteStringBlock = builder.newTargetBlock();
builder.addBranch(oneByteStringBlock, twoByteStringBlock);
final joinBlock = builder.newJoinBlock();
final resultVar = builder.declareLocalVariable(
'#result',
null,
const StringType(),
);
builder.startBlock(oneByteStringBlock);
builder.addLoadExternalField(
objectLayout.Thread_predefined_symbols_address,
hasObject: false,
);
builder.push(string);
builder.push(checkedIndex);
builder.addLoadArrayElement(.oneByteString, const IntType());
assert(objectLayout.vmOffsets.Symbols_kNumberOfOneCharCodeSymbols >= 256);
builder.addLoadExternalArrayElement(const StringType());
builder.addStoreLocal(resultVar);
builder.addGoto(joinBlock);
builder.startBlock(twoByteStringBlock);
builder.push(string);
builder.push(checkedIndex);
final codeUnit = builder.addLoadArrayElement(.twoByteString, const IntType());
builder.addIntConstant(
objectLayout.vmOffsets.Symbols_kNumberOfOneCharCodeSymbols,
);
builder.addComparison(.intGreaterOrEqual);
final oneByteCodeUnitBlock = builder.newTargetBlock();
final twoByteCodeUnitBlock = builder.newTargetBlock();
builder.addBranch(oneByteCodeUnitBlock, twoByteCodeUnitBlock);
builder.startBlock(oneByteCodeUnitBlock);
builder.addLoadExternalField(
objectLayout.Thread_predefined_symbols_address,
hasObject: false,
);
builder.push(codeUnit);
builder.addLoadExternalArrayElement(const StringType());
builder.addStoreLocal(resultVar);
builder.addGoto(joinBlock);
builder.startBlock(twoByteCodeUnitBlock);
builder.push(string);
builder.push(index);
buildNativeMethod(builder, functionRegistry, function);
builder.addStoreLocal(resultVar);
builder.addGoto(joinBlock);
builder.startBlock(joinBlock);
builder.addLoadLocal(resultVar);
}
/// Build IR for _GrowableList._withData factory constructor.
void buildGrowableListWithData(
FlowGraphBuilder builder,
ObjectLayout objectLayout,
ast.Class cls,
) {
final data = builder.pop();
final typeArgs = builder.pop();
final coreTypes = GlobalContext.instance.coreTypes;
final type = StaticType(coreTypes.thisInterfaceType(cls, .nonNullable));
final obj = builder.addAllocateObject(type, typeArguments: typeArgs);
builder.push(obj);
builder.push(data);
builder.addStoreInstanceField(objectLayout.GrowableList_data);
builder.push(obj);
builder.addIntConstant(0);
builder.addStoreInstanceField(objectLayout.GrowableList_length);
}
/// Build IR for _GrowableList._capacity getter.
void buildGrowableListCapacity(
FlowGraphBuilder builder,
ObjectLayout objectLayout,
) {
builder.addLoadInstanceField(objectLayout.GrowableList_data);
builder.addLoadInstanceField(objectLayout.Array_length);
}
/// Build IR for ThreadLocal._hasValue.
void buildThreadLocalHasValue(
FlowGraphBuilder builder,
ObjectLayout objectLayout,
) {
// if (id >= Thread.threadLocals.length) return false;
final id = builder.stackTop;
final array = builder.addLoadExternalField(
objectLayout.Thread_threadLocals,
hasObject: false,
);
builder.addLoadInstanceField(objectLayout.Array_length);
builder.addComparison(.intGreaterOrEqual);
final failBlock = builder.newTargetBlock();
final continueBlock = builder.newTargetBlock();
builder.addBranch(failBlock, continueBlock);
final joinBlock = builder.newJoinBlock();
final resultVar = builder.declareLocalVariable(
'#result',
null,
const BoolType(),
);
// return (Thread.threadLocals[id] != sentinel);
builder.startBlock(continueBlock);
builder.push(array);
builder.push(id);
builder.addLoadArrayElement(.fixedLengthList, const LateValueType());
builder.addSentinelConstant();
builder.addComparison(.notEqual);
builder.addStoreLocal(resultVar);
builder.addGoto(joinBlock);
builder.startBlock(failBlock);
builder.addBoolConstant(false);
builder.addStoreLocal(resultVar);
builder.addGoto(joinBlock);
builder.startBlock(joinBlock);
builder.addLoadLocal(resultVar);
}
/// Build IR for ThreadLocal._getValue.
void buildThreadLocalGetValue(
FlowGraphBuilder builder,
ObjectLayout objectLayout,
) {
// return Thread.threadLocals[id];
final id = builder.pop();
builder.addLoadExternalField(
objectLayout.Thread_threadLocals,
hasObject: false,
);
builder.push(id);
builder.addLoadArrayElement(.fixedLengthList, const LateValueType());
builder.addTypeCast(const TopType(), isChecked: false);
}
/// Build IR for unimplemented methods marked with 'vm:recognized' pragma.
void buildUnimplementedRecognizedMethod(
FlowGraphBuilder builder,
CFunction function,
) {
// Drop parameters.
for (var i = 0, n = function.numberOfParameters; i < n; ++i) {
builder.pop();
}
builder.addConstant(
ConstantValue.fromString('Unimplemented recognized method: $function'),
);
builder.addThrow(.exception, 1);
}
extension on ArrayKind {
String get elementName => switch (this) {
.int8List => 'Int8',
.uint8List => 'Uint8',
.uint8ClampedList => 'Uint8Clamped',
.int16List => 'Int16',
.uint16List => 'Uint16',
.int32List => 'Int32',
.uint32List => 'Uint32',
.int64List => 'Int64',
.uint64List => 'Uint64',
.fixedLengthList ||
.oneByteString ||
.twoByteString => throw 'ArrayKind.elementName is not defined for $this',
};
}
/// VM-specific recognized methods.
final class VmRecognizedMethods(
final FunctionRegistry functionRegistry,
final ObjectLayout objectLayout,
) extends CommonRecognizedMethods {
final coreTypes = GlobalContext.instance.coreTypes;
@override
BuildIR? getRecognizedFunctionBody(CFunction function) {
final commonBuilder = super.getRecognizedFunctionBody(function);
if (commonBuilder != null) {
return commonBuilder;
}
final member = function.member;
if (member.isRecognized(coreTypes)) {
final builder = _recognizedMembers[member];
if (builder != null) {
return builder;
}
if (member.isExternal) {
return (FlowGraphBuilder builder) {
buildUnimplementedRecognizedMethod(builder, function);
};
}
}
if (member.isExternal) {
if (getExternalName(coreTypes, member) != null) {
return (FlowGraphBuilder builder) {
buildNativeMethod(builder, functionRegistry, function);
};
}
}
return null;
}
late final _recognizedMembers = <ast.Member, BuildIR>{
// dart:core
index.getProcedure(
'dart:core',
'Object',
'==',
): (FlowGraphBuilder builder) {
buildComparisonOp(builder, .equal);
},
index.getProcedure(
'dart:core',
'_Smi',
'get:hashCode',
): (FlowGraphBuilder builder) {
buildUnaryIntOp(builder, .hash);
},
index.getProcedure(
'dart:core',
'_Smi',
'get:bitLength',
): (FlowGraphBuilder builder) {
buildUnaryIntOp(builder, .bitLength);
},
index.getProcedure(
'dart:core',
'_Mint',
'get:hashCode',
): (FlowGraphBuilder builder) {
buildUnaryIntOp(builder, .hash);
},
index.getProcedure(
'dart:core',
'_Mint',
'get:bitLength',
): (FlowGraphBuilder builder) {
buildUnaryIntOp(builder, .bitLength);
},
// TODO: implement 'operator ==' instead of '_equalToInteger'
index.getProcedure(
'dart:core',
'_IntegerImplementation',
'_equalToInteger',
): (FlowGraphBuilder builder) {
buildComparisonOp(builder, .intEqual);
},
index.getProcedure(
'dart:core',
'_StringBase',
'get:length',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.StringBase_length);
},
index.getProcedure(
'dart:core',
'_StringBase',
'codeUnitAt',
): (FlowGraphBuilder builder) {
buildStringBaseCodeUnitAt(builder, objectLayout);
},
index.getProcedure(
'dart:core',
'_StringBase',
'[]',
): (FlowGraphBuilder builder) {
buildStringBaseCharAt(
builder,
functionRegistry,
objectLayout,
builder.graph.function,
);
},
index.getProcedure(
'dart:core',
'_Array',
'get:length',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.Array_length);
},
index.getProcedure(
'dart:core',
'_Array',
'[]',
): (FlowGraphBuilder builder) {
buildArrayElementGetter(
builder,
.fixedLengthList,
objectLayout.Array_length,
StaticType(
ast.TypeParameterType.withDefaultNullability(
index.getClass('dart:core', '_Array').typeParameters.single,
),
),
);
},
index.getProcedure('dart:core', '_List', ''): (FlowGraphBuilder builder) {
buildArrayFactory(
builder,
.fixedLengthList,
index.getClass('dart:core', '_List'),
);
},
index.getProcedure(
'dart:core',
'_List',
'[]=',
): (FlowGraphBuilder builder) {
buildArrayElementSetter(
builder,
.fixedLengthList,
objectLayout.Array_length,
);
},
index.getProcedure(
'dart:core',
'_GrowableList',
'_withData',
): (FlowGraphBuilder builder) {
buildGrowableListWithData(
builder,
objectLayout,
index.getClass('dart:core', '_GrowableList'),
);
},
index.getProcedure(
'dart:core',
'_GrowableList',
'get:_emptyList',
): (FlowGraphBuilder builder) {
buildConstantGetter(
builder,
ConstantValue(RuntimeConstantObject(.mutableEmptyList)),
);
},
index.getProcedure(
'dart:core',
'_GrowableList',
'get:length',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.GrowableList_length);
},
index.getProcedure(
'dart:core',
'_GrowableList',
'_setLength',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.GrowableList_length);
},
index.getProcedure(
'dart:core',
'_GrowableList',
'get:_capacity',
): (FlowGraphBuilder builder) {
buildGrowableListCapacity(builder, objectLayout);
},
index.getProcedure(
'dart:core',
'_GrowableList',
'_setData',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.GrowableList_data);
},
index.getProcedure(
'dart:core',
'_GrowableList',
'[]',
): (FlowGraphBuilder builder) {
buildArrayElementGetter(
builder,
.fixedLengthList, // Backing store array.
objectLayout.GrowableList_length,
StaticType(
ast.TypeParameterType.withDefaultNullability(
index.getClass('dart:core', '_GrowableList').typeParameters.single,
),
),
indirectDataField: objectLayout.GrowableList_data,
);
},
index.getProcedure(
'dart:core',
'_GrowableList',
'[]=',
): (FlowGraphBuilder builder) {
buildArrayElementSetter(
builder,
.fixedLengthList, // Backing store array.
objectLayout.GrowableList_length,
indirectDataField: objectLayout.GrowableList_data,
);
},
index.getProcedure(
'dart:core',
'_GrowableList',
'_setIndexed',
): (FlowGraphBuilder builder) {
buildArrayElementSetter(
builder,
.fixedLengthList, // Backing store array.
objectLayout.GrowableList_length,
indirectDataField: objectLayout.GrowableList_data,
);
},
// dart:_compact_hash
index.getTopLevelProcedure(
'dart:_compact_hash',
'get:_uninitializedIndex',
): (FlowGraphBuilder builder) {
buildConstantGetter(
builder,
ConstantValue(RuntimeConstantObject(.uninitializedIndex)),
);
},
index.getTopLevelProcedure(
'dart:_compact_hash',
'get:_uninitializedData',
): (FlowGraphBuilder builder) {
buildConstantGetter(
builder,
ConstantValue(RuntimeConstantObject(.uninitializedData)),
);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashBase',
'get:_index',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.LinkedHashBase_index);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashBase',
'set:_index',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.LinkedHashBase_index);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashBase',
'get:_hashMask',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.LinkedHashBase_hashMask);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashBase',
'set:_hashMask',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.LinkedHashBase_hashMask);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashBase',
'get:_data',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.LinkedHashBase_data);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashBase',
'set:_data',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.LinkedHashBase_data);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashBase',
'get:_usedData',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.LinkedHashBase_usedData);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashBase',
'set:_usedData',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.LinkedHashBase_usedData);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashBase',
'get:_deletedKeys',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.LinkedHashBase_deletedKeys);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashBase',
'set:_deletedKeys',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.LinkedHashBase_deletedKeys);
},
index.getProcedure(
'dart:_compact_hash',
'_LinkedHashImmutableBase',
'get:_data',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.LinkedHashBase_data);
},
// dart:_internal
index.getTopLevelProcedure(
'dart:_internal',
'get:has63BitSmis',
): (FlowGraphBuilder builder) {
final totalSmiBits =
smiBits(objectLayout.compressedWordSize) + 1; // Including sign bit.
final has63BitSmis = totalSmiBits >= 63;
buildConstantGetter(builder, ConstantValue.fromBool(has63BitSmis));
},
index.getTopLevelProcedure(
'dart:_internal',
'allocateOneByteString',
): (FlowGraphBuilder builder) {
buildArrayFactory(
builder,
.oneByteString,
index.getClass('dart:core', '_OneByteString'),
);
},
index.getTopLevelProcedure(
'dart:_internal',
'allocateTwoByteString',
): (FlowGraphBuilder builder) {
buildArrayFactory(
builder,
.twoByteString,
index.getClass('dart:core', '_TwoByteString'),
);
},
index.getTopLevelProcedure(
'dart:_internal',
'writeIntoOneByteString',
): (FlowGraphBuilder builder) {
buildArrayElementSetter(
builder,
.oneByteString,
objectLayout.StringBase_length,
checkIndex: false,
);
},
index.getTopLevelProcedure(
'dart:_internal',
'writeIntoTwoByteString',
): (FlowGraphBuilder builder) {
buildArrayElementSetter(
builder,
.twoByteString,
objectLayout.StringBase_length,
checkIndex: false,
);
},
index.getProcedure(
'dart:_internal',
'ClassID',
'getID',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.Object_classId);
},
// dart:async
index.getProcedure(
'dart:async',
'_SuspendState',
'get:_functionData',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.SuspendState_functionData);
},
index.getProcedure(
'dart:async',
'_SuspendState',
'set:_functionData',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.SuspendState_functionData);
},
index.getProcedure(
'dart:async',
'_SuspendState',
'get:_thenCallback',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.SuspendState_thenCallback);
},
index.getProcedure(
'dart:async',
'_SuspendState',
'set:_thenCallback',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.SuspendState_thenCallback);
},
index.getProcedure(
'dart:async',
'_SuspendState',
'get:_errorCallback',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.SuspendState_errorCallback);
},
index.getProcedure(
'dart:async',
'_SuspendState',
'set:_errorCallback',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.SuspendState_errorCallback);
},
// dart:isolate
index.getProcedure(
'dart:isolate',
'_RawReceivePort',
'get:_handler',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.RawReceivePort_handler);
},
index.getProcedure(
'dart:isolate',
'_RawReceivePort',
'set:_handler',
): (FlowGraphBuilder builder) {
buildInstanceSetter(builder, objectLayout.RawReceivePort_handler);
},
index.getProcedure(
'dart:isolate',
'_RawReceivePort',
'get:sendPort',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.RawReceivePort_sendPort);
},
// dart:typed_data
index.getProcedure(
'dart:typed_data',
'_TypedListBase',
'get:length',
): (FlowGraphBuilder builder) {
buildInstanceGetter(builder, objectLayout.TypedListBase_length);
},
for (ArrayKind arrayKind in [
.int8List,
.uint8List,
.uint8ClampedList,
.int16List,
.uint16List,
.int32List,
.uint32List,
.int64List,
.uint64List,
])
index.getProcedure(
'dart:typed_data',
'_${arrayKind.elementName}List',
'[]',
): (FlowGraphBuilder builder) {
buildArrayElementGetter(
builder,
arrayKind,
objectLayout.TypedListBase_length,
const IntType(),
);
},
for (ArrayKind arrayKind in [
.int8List,
.uint8List,
.uint8ClampedList,
.int16List,
.uint16List,
.int32List,
.uint32List,
.int64List,
.uint64List,
])
index.getProcedure(
'dart:typed_data',
'_${arrayKind.elementName}List',
'[]=',
): (FlowGraphBuilder builder) {
buildArrayElementSetter(
builder,
arrayKind,
objectLayout.TypedListBase_length,
);
},
for (ArrayKind arrayKind in [
.int8List,
.uint8List,
.uint8ClampedList,
.int16List,
.uint16List,
.int32List,
.uint32List,
.int64List,
.uint64List,
])
index.getProcedure(
'dart:typed_data',
'${arrayKind.elementName}List',
'',
): (FlowGraphBuilder builder) {
buildArrayFactory(
builder,
arrayKind,
index.getClass('dart:typed_data', '${arrayKind.elementName}List'),
);
},
// dart:_vm
index.getProcedure(
'dart:_vm',
'ThreadLocal',
'_hasValue',
): (FlowGraphBuilder builder) {
buildThreadLocalHasValue(builder, objectLayout);
},
index.getProcedure(
'dart:_vm',
'ThreadLocal',
'_getValue',
): (FlowGraphBuilder builder) {
buildThreadLocalGetValue(builder, objectLayout);
},
};
}