// 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. library vm.bytecode.gen_bytecode; import 'package:front_end/src/api_unstable/vm.dart' show CompilerContext, Severity, isRedirectingFactoryField, messageBytecodeLimitExceededTooManyArguments, noLength, templateIllegalRecursiveType; import 'package:kernel/ast.dart' hide MapEntry, Component, FunctionDeclaration; import 'package:kernel/ast.dart' as ast show Component, FunctionDeclaration; import 'package:kernel/class_hierarchy.dart' show ClassHierarchy; import 'package:kernel/core_types.dart' show CoreTypes; import 'package:kernel/external_name.dart' show getExternalName, getNativeExtensionUris; import 'package:kernel/library_index.dart' show LibraryIndex; import 'package:kernel/text/ast_to_text.dart' show globalDebuggingNames, NameSystem; import 'package:kernel/type_algebra.dart' show Substitution, containsTypeVariable; import 'package:kernel/type_environment.dart' show StatefulStaticTypeContext, SubtypeCheckMode, TypeEnvironment; import 'assembler.dart'; import 'bytecode_serialization.dart' show StringTable; import 'constant_pool.dart'; import 'dbc.dart'; import 'declarations.dart'; import 'exceptions.dart'; import 'generics.dart' show flattenInstantiatorTypeArguments, getDefaultFunctionTypeArguments, getInstantiatorTypeArguments, getStaticType, getTypeParameterTypes, hasFreeTypeParameters, hasInstantiatorTypeArguments, isAllDynamic, isInstantiatedInterfaceCall, isUncheckedCall, isUncheckedClosureCall; import 'local_variable_table.dart' show LocalVariableTable; import 'local_vars.dart' show LocalVariables; import 'nullability_detector.dart' show NullabilityDetector; import 'object_table.dart' show ObjectHandle, ObjectTable, NameAndType, topLevelClassName; import 'options.dart' show BytecodeOptions; import 'recognized_methods.dart' show RecognizedMethods; import 'recursive_types_validator.dart' show IllegalRecursiveTypeException; import 'source_positions.dart' show LineStarts, SourcePositions; import '../metadata/bytecode.dart'; import '../metadata/direct_call.dart' show DirectCallMetadata, DirectCallMetadataRepository; import '../metadata/inferred_type.dart' show InferredType, InferredTypeMetadataRepository; import '../metadata/obfuscation_prohibitions.dart' show ObfuscationProhibitionsMetadataRepository; import '../metadata/procedure_attributes.dart' show ProcedureAttributesMetadata, ProcedureAttributesMetadataRepository; import 'dart:convert' show utf8; import 'dart:developer'; import 'dart:math' as math; // This symbol is used as the name in assert assignable's to indicate it comes // from an explicit 'as' check. This will cause the runtime to throw the right // exception. const String symbolForTypeCast = ' in type cast'; void generateBytecode( ast.Component component, { BytecodeOptions options, List libraries, CoreTypes coreTypes, ClassHierarchy hierarchy, }) { Timeline.timeSync("generateBytecode", () { options ??= new BytecodeOptions(); verifyBytecodeInstructionDeclarations(); coreTypes ??= new CoreTypes(component); void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {} hierarchy ??= new ClassHierarchy(component, coreTypes, onAmbiguousSupertypes: ignoreAmbiguousSupertypes); final typeEnvironment = new TypeEnvironment(coreTypes, hierarchy); libraries ??= component.libraries; // Save/restore global NameSystem to avoid accumulating garbage. // NameSystem holds the whole AST as it is strongly connected due to // parent pointers. Objects are added to NameSystem when toString() // is called from AST nodes. Bytecode generator widely uses // Expression.getStaticType, which calls Expression.getStaticTypeAsInstanceOf, // which uses toString() when it crashes due to http://dartbug.com/34496. final savedGlobalDebuggingNames = globalDebuggingNames; globalDebuggingNames = new NameSystem(); Library library; try { final bytecodeGenerator = new BytecodeGenerator( component, coreTypes, hierarchy, typeEnvironment, options); for (library in libraries) { bytecodeGenerator.visitLibrary(library); } } on IllegalRecursiveTypeException catch (e) { CompilerContext.current.options.report( templateIllegalRecursiveType .withArguments(e.type, library.isNonNullableByDefault) .withoutLocation(), Severity.error); } finally { globalDebuggingNames = savedGlobalDebuggingNames; } }); } class BytecodeGenerator extends RecursiveVisitor { static final Name callName = new Name('call'); static final Name noSuchMethodName = new Name('noSuchMethod'); final CoreTypes coreTypes; final ClassHierarchy hierarchy; final TypeEnvironment typeEnvironment; final StatefulStaticTypeContext staticTypeContext; final BytecodeOptions options; final BytecodeMetadataRepository metadata = new BytecodeMetadataRepository(); final RecognizedMethods recognizedMethods; final int formatVersion; final Map astUriToSource; StringTable stringTable; ObjectTable objectTable; Component bytecodeComponent; NullabilityDetector nullabilityDetector; Map directCallMetadata; ProcedureAttributesMetadataRepository procedureAttributesMetadataRepository; ProcedureAttributesMetadata procedureAttributesMetadata; Map inferredTypeMetadata; List inferredTypesAttribute; List classDeclarations; List fieldDeclarations; List functionDeclarations; Class enclosingClass; Member enclosingMember; FunctionNode enclosingFunction; FunctionNode parentFunction; bool isClosure; Set classTypeParameters; List functionTypeParameters; Set functionTypeParametersSet; List instantiatorTypeArguments; LocalVariables locals; Map labeledStatements; Map switchCases; Map tryCatches; Map> finallyBlocks; List