These changes are causing a segfault in DartEntry::InvokeFunction in dart_entry.cc in Flutter,

which was blocking the Dart SDK roll.

Revert "Take 3 for "[vm/kernel/precomp] Remove procedures from entry points files.""

This reverts commit 567109df7f.

Revert "[vm/precomp] Extend @pragma entry-points to classes."

This reverts commit 232698047c.

Change-Id: Ib63d1afb8a1c978be7ddf282af0e7d5547111cc3
Reviewed-on: https://dart-review.googlesource.com/67300
Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Ben Konyi 2018-07-28 00:01:50 +00:00
parent 6e322f794c
commit 08f59e5de3
68 changed files with 2439 additions and 2039 deletions

View file

@ -102,6 +102,7 @@ Future<int> compile(List<String> arguments) async {
entryPoints.addAll([
'pkg/vm/lib/transformations/type_flow/entry_points.json',
'pkg/vm/lib/transformations/type_flow/entry_points_extra.json',
'pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json',
]);
}

View file

@ -1180,7 +1180,7 @@ class TypeFlowAnalysis implements EntryPointsListener, CallHandler {
TypeFlowAnalysis(Component component, CoreTypes coreTypes,
ClosedWorldClassHierarchy hierarchy, this.environment, this.libraryIndex,
{List<String> entryPointsJSONFiles, EntryPointsAnnotationMatcher matcher})
{List<String> entryPointsJSONFiles})
: nativeCodeOracle = new NativeCodeOracle(libraryIndex) {
hierarchyCache = new _ClassHierarchyCache(this, hierarchy);
summaryCollector =
@ -1192,10 +1192,7 @@ class TypeFlowAnalysis implements EntryPointsListener, CallHandler {
nativeCodeOracle.processEntryPointsJSONFiles(entryPointsJSONFiles, this);
}
matcher ??= new ConstantEntryPointsAnnotationMatcher(coreTypes);
component
.accept(new PragmaEntryPointsVisitor(this, nativeCodeOracle, matcher));
component.accept(new PragmaEntryPointsVisitor(coreTypes, this));
}
_Invocation get currentInvocation => workList.callStack.last;

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,85 @@
{
"roots": [
{
"library": "dart:core",
"class": "Object",
"name": "noSuchMethod",
"action": "call"
},
{
"library": "dart:core",
"class": "Object",
"name": "_haveSameRuntimeType",
"action": "call"
},
{
"library": "dart:core",
"class": "Object",
"name": "_instanceOf",
"action": "call"
},
{
"library": "dart:core",
"class": "List",
"name": "_fromLiteral",
"action": "call"
},
{
"library": "dart:core",
"class": "Map",
"name": "_fromLiteral",
"action": "call"
},
{
"library": "dart:core",
"class": "_ImmutableList",
"action": "create-instance"
},
{
"library": "dart:core",
"class": "_ImmutableMap",
"action": "create-instance"
},
{
"library": "dart:core",
"class": "_ImmutableMap",
"name": "_create",
"action": "call"
},
{
"library": "dart:core",
"class": "_StringBase",
"name": "_interpolate",
"action": "call"
},
{
"library": "dart:core",
"class": "_StringBase",
"name": "_interpolateSingle",
"action": "call"
},
{
"library": "dart:core",
"name": "_classRangeAssert",
"action": "call"
},
{
"library": "dart:core",
"name": "_classIdEqualsAssert",
"action": "call"
},
{
"library": "dart:core",
"class": "_AssertionError",
"name": "_evaluateAssertion",
"action": "call"
},
{
"library": "dart:core",
"class": "_AssertionError",
"name": "_throwNew",
"action": "call"
},
{
"library": "dart:core",
"class": "_Closure",
@ -35,6 +115,64 @@
"class": "_Closure",
"name": "_hash",
"action": "get"
},
{
"library": "dart:core",
"class": "_CompileTimeError",
"action": "create-instance"
},
{
"library": "dart:core",
"class": "Object",
"name": "_simpleInstanceOf",
"action": "call"
},
{
"library": "dart:core",
"class": "Object",
"name": "_simpleInstanceOfTrue",
"action": "call"
},
{
"library": "dart:core",
"class": "Object",
"name": "_simpleInstanceOfFalse",
"action": "call"
},
{
"library": "dart:_internal",
"name": "_classRangeCheck",
"action": "call"
},
{
"library": "dart:_internal",
"name": "_prependTypeArguments",
"action": "call"
},
{
"library": "dart:async",
"name": "_setAsyncThreadStackTrace",
"action": "call"
},
{
"library": "dart:async",
"name": "_clearAsyncThreadStackTrace",
"action": "call"
},
{
"library": "dart:async",
"name": "_asyncStarMoveNextHelper",
"action": "call"
},
{
"library": "dart:async",
"name": "_completeOnAsyncReturn",
"action": "call"
},
{
"library": "dart:async",
"class": "_AsyncStarStreamController",
"action": "create-instance"
}
]
}

View file

@ -0,0 +1,9 @@
{
"roots": [
{
"library": "dart:_builtin",
"name": "_resolveScriptUri",
"action": "call"
}
]
}

View file

@ -29,23 +29,25 @@ abstract class EntryPointsListener {
ConcreteType addAllocatedClass(Class c);
}
abstract class EntryPointsAnnotationMatcher {
bool annotationsDefineRoot(List<Expression> annotations);
}
class ConstantEntryPointsAnnotationMatcher
implements EntryPointsAnnotationMatcher {
/// Some entry points are not listed in any JSON file but are marked with the
/// `@pragma('vm.entry_point', ...)` annotation instead.
///
/// Currently Procedure`s (action "call") can be annotated in this way.
//
// TODO(sjindel): Support all types of entry points.
class PragmaEntryPointsVisitor extends RecursiveVisitor {
final EntryPointsListener entryPoints;
final CoreTypes coreTypes;
ConstantEntryPointsAnnotationMatcher(this.coreTypes);
PragmaEntryPointsVisitor(this.coreTypes, this.entryPoints);
bool definesRoot(InstanceConstant constant) {
bool _definesRoot(InstanceConstant constant) {
if (constant.classReference.node != coreTypes.pragmaClass) return false;
Constant name = constant.fieldValues[coreTypes.pragmaName.reference];
assertx(name != null);
if (name is! StringConstant ||
(name as StringConstant).value != "vm.entry-point") {
(name as StringConstant).value != "vm.entry_point") {
return false;
}
@ -55,66 +57,34 @@ class ConstantEntryPointsAnnotationMatcher
return options is BoolConstant && options.value;
}
@override
bool annotationsDefineRoot(List<Expression> annotations) {
bool _annotationsDefineRoot(List<Expression> annotations) {
for (var annotation in annotations) {
if (annotation is ConstantExpression) {
Constant constant = annotation.constant;
if (constant is InstanceConstant) {
if (definesRoot(constant)) {
if (_definesRoot(constant)) {
return true;
}
}
} else {
throw "All annotations must be constants!";
}
}
return false;
}
}
/// Some entry points are not listed in any JSON file but are marked with the
/// `@pragma('vm.entry-point', ...)` annotation instead.
///
/// Currently Procedure`s (action "call") can be annotated in this way.
//
// TODO(sjindel): Support all types of entry points.
class PragmaEntryPointsVisitor extends RecursiveVisitor {
final EntryPointsListener entryPoints;
final NativeCodeOracle nativeCodeOracle;
final EntryPointsAnnotationMatcher matcher;
Class currentClass = null;
PragmaEntryPointsVisitor(
this.entryPoints, this.nativeCodeOracle, this.matcher);
@override
visitClass(Class klass) {
if (matcher.annotationsDefineRoot(klass.annotations)) {
if (_annotationsDefineRoot(klass.annotations)) {
entryPoints.addAllocatedClass(klass);
}
currentClass = klass;
klass.visitChildren(this);
}
@override
visitProcedure(Procedure proc) {
if (matcher.annotationsDefineRoot(proc.annotations)) {
assertx(!proc.isGetter && !proc.isSetter);
if (_annotationsDefineRoot(proc.annotations)) {
entryPoints.addRawCall(proc.isInstanceMember
? new InterfaceSelector(proc, callKind: CallKind.Method)
: new DirectSelector(proc, callKind: CallKind.Method));
nativeCodeOracle.setMemberReferencedFromNativeCode(proc);
}
}
@override
visitConstructor(Constructor ctor) {
if (matcher.annotationsDefineRoot(ctor.annotations)) {
entryPoints
.addRawCall(new DirectSelector(ctor, callKind: CallKind.Method));
entryPoints.addAllocatedClass(currentClass);
nativeCodeOracle.setMemberReferencedFromNativeCode(ctor);
}
}
}
@ -131,9 +101,6 @@ class NativeCodeOracle {
bool isMemberReferencedFromNativeCode(Member member) =>
_membersReferencedFromNativeCode.contains(member);
void setMemberReferencedFromNativeCode(Member member) =>
_membersReferencedFromNativeCode.add(member);
/// Simulate the execution of a native method by adding its entry points
/// using [entryPointsListener]. Returns result type of the native method.
Type handleNativeProcedure(

View file

@ -14,7 +14,6 @@ import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/type_environment.dart';
import 'analysis.dart';
import 'native_code.dart';
import 'calls.dart';
import 'summary_collector.dart';
import 'types.dart';
@ -32,8 +31,7 @@ const bool kDumpClassHierarchy =
/// Whole-program type flow analysis and transformation.
/// Assumes strong mode and closed world.
Component transformComponent(
CoreTypes coreTypes, Component component, List<String> entryPoints,
[EntryPointsAnnotationMatcher matcher]) {
CoreTypes coreTypes, Component component, List<String> entryPoints) {
if ((entryPoints == null) || entryPoints.isEmpty) {
throw 'Error: unable to perform global type flow analysis without entry points.';
}
@ -55,7 +53,7 @@ Component transformComponent(
final typeFlowAnalysis = new TypeFlowAnalysis(
component, coreTypes, hierarchy, types, libraryIndex,
entryPointsJSONFiles: entryPoints, matcher: matcher);
entryPointsJSONFiles: entryPoints);
Procedure main = component.mainMethod;
final Selector mainSelector = new DirectSelector(main);

View file

@ -8,50 +8,13 @@ import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:test/test.dart';
import 'package:vm/transformations/type_flow/native_code.dart';
import 'package:vm/transformations/type_flow/transformer.dart'
show transformComponent;
import 'package:vm/transformations/type_flow/utils.dart';
import '../../common_test_utils.dart';
final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
// Since we don't run the constants transformation in this test, we can't
// recognize all pragma annotations precisely. Instead, we pattern match on
// annotations which look like a pragma and assume that their options field
// evaluates to true.
class ExpressionEntryPointsAnnotationMatcher
extends EntryPointsAnnotationMatcher {
final CoreTypes coreTypes;
ExpressionEntryPointsAnnotationMatcher(this.coreTypes);
bool _looksLikePragma(ConstructorInvocation annotation) {
if (annotation.target.parent != coreTypes.pragmaClass) return false;
if (annotation.arguments.types.length != 0 ||
annotation.arguments.positional.length < 1 ||
annotation.arguments.named.length != 0) {
throw "Cannot evaluate pragma annotation $annotation";
}
var argument = annotation.arguments.positional[0];
return argument is StringLiteral && argument.value == "vm.entry-point";
}
@override
bool annotationsDefineRoot(List<Expression> annotations) {
for (var annotation in annotations) {
assertx(annotation is! ConstantExpression);
if (annotation is ConstructorInvocation && _looksLikePragma(annotation)) {
return true;
}
}
return false;
}
}
runTestCase(Uri source) async {
Component component = await compileTestCaseToKernelProgram(source);
@ -62,8 +25,7 @@ runTestCase(Uri source) async {
pkgVmDir + '/lib/transformations/type_flow/entry_points_extra.json',
];
component = transformComponent(coreTypes, component, entryPoints,
new ExpressionEntryPointsAnnotationMatcher(coreTypes));
component = transformComponent(coreTypes, component, entryPoints);
final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);

View file

@ -90,7 +90,8 @@ export DART_CONFIGURATION=${DART_CONFIGURATION:-ReleaseX64}
BIN_DIR="$OUT_DIR/$DART_CONFIGURATION"
ENTRY_POINTS="--entry-points ${BIN_DIR}/gen/runtime/bin/precompiler_entry_points.json \
--entry-points ${SDK_DIR}/pkg/vm/lib/transformations/type_flow/entry_points_extra.json"
--entry-points ${SDK_DIR}/pkg/vm/lib/transformations/type_flow/entry_points_extra.json \
--entry-points ${SDK_DIR}/pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json"
# Step 1: Generate Kernel binary from the input Dart source.
"$BIN_DIR"/dart \
@ -115,4 +116,4 @@ ENTRY_POINTS="--entry-points ${BIN_DIR}/gen/runtime/bin/precompiler_entry_points
# Step 3: Assemble the assembly file into an ELF object.
if [ $BUILD_ELF -eq 1 ]; then
gcc -shared -o "$SNAPSHOT_FILE" "$DART_BOOTSTRAP_OUT"
fi
fi

View file

@ -28,7 +28,6 @@ void _print(arg) {
_printString(arg.toString());
}
@pragma("vm.entry-point")
_getPrintClosure() => _print;
// Asynchronous loading of resources.
@ -138,7 +137,6 @@ _enforceTrailingSlash(uri) {
// Embedder Entrypoint:
// The embedder calls this method with the current working directory.
@pragma("vm.entry-point")
void _setWorkingDirectory(String cwd) {
if (!_setupCompleted) {
_setupHooks();
@ -154,7 +152,6 @@ void _setWorkingDirectory(String cwd) {
// Embedder Entrypoint:
// The embedder calls this method with a custom package root.
@pragma("vm.entry-point")
String _setPackageRoot(String packageRoot) {
if (!_setupCompleted) {
_setupHooks();
@ -185,7 +182,6 @@ String _setPackageRoot(String packageRoot) {
}
// Embedder Entrypoint:
@pragma("vm.entry-point")
String _setPackagesMap(String packagesParam) {
if (!_setupCompleted) {
_setupHooks();
@ -217,7 +213,6 @@ String _setPackagesMap(String packagesParam) {
// Resolves the script uri in the current working directory iff the given uri
// did not specify a scheme (e.g. a path to a script file on the command line).
@pragma("vm.entry-point")
String _resolveScriptUri(String scriptName) {
if (_traceLoading) {
_log("Resolving script: $scriptName");
@ -246,7 +241,6 @@ String _resolveScriptUri(String scriptName) {
// Embedder Entrypoint (gen_snapshot):
// Resolve relative paths relative to working directory.
@pragma("vm.entry-point")
String _resolveInWorkingDirectory(String fileName) {
if (!_setupCompleted) {
_setupHooks();
@ -303,7 +297,6 @@ String _filePathFromUri(String userUri) {
}
// Embedder Entrypoint.
@pragma("vm.entry-point")
_libraryFilePath(String libraryUri) {
if (!_setupCompleted) {
_setupHooks();
@ -319,7 +312,6 @@ _libraryFilePath(String libraryUri) {
}
// Register callbacks and hooks with the rest of the core libraries.
@pragma("vm.entry-point")
_setupHooks() {
_setupCompleted = true;
VMLibraryHooks.resourceReadAsBytes = _resourceReadAsBytes;

View file

@ -55,7 +55,6 @@ class _IOCrypto {
static Uint8List getRandomBytes(int count) native "Crypto_GetRandomBytes";
}
@pragma("vm.entry-point")
_setupHooks() {
VMLibraryHooks.eventHandlerSendData = _EventHandler._sendData;
VMLibraryHooks.timerMillisecondClock = _EventHandler._timerMillisecondClock;

View file

@ -67,5 +67,4 @@ Uri _uriBaseClosure() {
return new Uri.directory(result);
}
@pragma("vm.entry-point")
_getUriBaseClosure() => _uriBaseClosure;

View file

@ -414,7 +414,6 @@ class _FSEventStreamFileSystemWatcher extends _FileSystemWatcher {
}
}
@pragma("vm.entry-point")
Uint8List _makeUint8ListView(Uint8List source, int offsetInBytes, int length) {
return new Uint8List.view(source.buffer, offsetInBytes, length);
}

View file

@ -889,20 +889,46 @@ static void ReadFile(const char* filename, uint8_t** buffer, intptr_t* size) {
static Dart_QualifiedFunctionName standalone_entry_points[] = {
// Functions.
{"dart:_builtin", "::", "_getPrintClosure"},
{"dart:_builtin", "::", "_libraryFilePath"},
{"dart:_builtin", "::", "_resolveInWorkingDirectory"},
{"dart:_builtin", "::", "_setPackageRoot"},
{"dart:_builtin", "::", "_setPackagesMap"},
{"dart:_builtin", "::", "_setWorkingDirectory"},
{"dart:async", "::", "_setScheduleImmediateClosure"},
{"dart:cli", "::", "_getWaitForEvent"},
{"dart:cli", "::", "_waitForEventClosure"},
{"dart:io", "::", "_getUriBaseClosure"},
{"dart:io", "::", "_getWatchSignalInternal"},
{"dart:io", "::", "_makeDatagram"},
{"dart:io", "::", "_makeUint8ListView"},
{"dart:io", "::", "_setupHooks"},
{"dart:io", "_EmbedderConfig", "_mayExit"},
{"dart:io", "_ExternalBuffer", "get:end"},
{"dart:io", "_ExternalBuffer", "get:start"},
{"dart:io", "_ExternalBuffer", "set:data"},
{"dart:io", "_ExternalBuffer", "set:end"},
{"dart:io", "_ExternalBuffer", "set:start"},
{"dart:io", "_Namespace", "_setupNamespace"},
{"dart:io", "_Platform", "set:_nativeScript"},
{"dart:io", "_ProcessStartStatus", "set:_errorCode"},
{"dart:io", "_ProcessStartStatus", "set:_errorMessage"},
{"dart:io", "_SecureFilterImpl", "get:buffers"},
{"dart:io", "_SecureFilterImpl", "get:ENCRYPTED_SIZE"},
{"dart:io", "_SecureFilterImpl", "get:SIZE"},
{"dart:io", "CertificateException", "CertificateException."},
{"dart:io", "Directory", "Directory."},
{"dart:io", "File", "File."},
{"dart:io", "FileSystemException", "FileSystemException."},
{"dart:io", "HandshakeException", "HandshakeException."},
{"dart:io", "Link", "Link."},
{"dart:io", "OSError", "OSError."},
{"dart:io", "TlsException", "TlsException."},
{"dart:io", "X509Certificate", "X509Certificate._"},
{"dart:isolate", "::", "_getIsolateScheduleImmediateClosure"},
{"dart:isolate", "::", "_setupHooks"},
{"dart:isolate", "::", "_startMainIsolate"},
// Fields
{"dart:io", "_EmbedderConfig", "_mayExit"},
{"dart:cli", "::", "_waitForEventClosure"},
{"dart:_builtin", "::", "_isolateId"},
{"dart:_builtin", "::", "_loadPort"},
{"dart:_internal", "::", "_printClosure"},

View file

@ -33,7 +33,6 @@ class _NamespaceImpl extends NativeFieldWrapperClass1 implements _Namespace {
@patch
class _Namespace {
@patch
@pragma("vm.entry-point")
static void _setupNamespace(var namespace) {
_NamespaceImpl._setupNamespace(namespace);
}

View file

@ -129,7 +129,6 @@ class _SignalController {
native "Process_ClearSignalHandler";
}
@pragma("vm.entry-point")
Function _getWatchSignalInternal() => _ProcessUtils._watchSignalInternal;
@patch

View file

@ -20,7 +20,6 @@ class _SecureFilter {
@patch
class X509Certificate {
@patch
@pragma("vm.entry-point")
factory X509Certificate._() => new _X509CertificateImpl();
}

View file

@ -1905,7 +1905,6 @@ class _RawDatagramSocket extends Stream<RawSocketEvent>
}
}
@pragma("vm.entry-point")
Datagram _makeDatagram(
List<int> data, String address, List<int> in_addr, int port) {
return new Datagram(data, new _InternetAddress(address, null, in_addr), port);

View file

@ -220,7 +220,7 @@ _registerSignalHandler() {
_signalSubscription = _signalWatch(ProcessSignal.SIGQUIT).listen(_onSignal);
}
@pragma("vm.entry-point", !const bool.fromEnvironment("dart.vm.product"))
@pragma("vm.entry_point", !const bool.fromEnvironment("dart.vm.product"))
main() {
// Set embedder hooks.
VMServiceEmbedderHooks.cleanup = cleanupCallback;

View file

@ -121,7 +121,6 @@ class _List<E> extends FixedLengthListBase<E> {
// classes (and inline cache misses) versus a field in the native
// implementation (checks when modifying). We should keep watching
// the inline cache misses.
@pragma("vm.entry-point")
class _ImmutableList<E> extends UnmodifiableListBase<E> {
factory _ImmutableList._uninstantiable() {
throw new UnsupportedError(

View file

@ -52,7 +52,6 @@ class List<E> {
// Factory constructing a mutable List from a parser generated List literal.
// [elements] contains elements that are already type checked.
@pragma("vm.entry-point")
factory List._fromLiteral(List elements) {
if (elements.isEmpty) {
return new _GrowableList<E>(0);

View file

@ -120,7 +120,6 @@ void _asyncStarListenHelper(var object, var awaiter) {
object._awaiter = awaiter;
}
@pragma("vm.entry-point")
void _asyncStarMoveNextHelper(var stream) {
if (stream is! _StreamImpl) {
return;
@ -135,7 +134,6 @@ void _asyncStarMoveNextHelper(var stream) {
// _AsyncStarStreamController is used by the compiler to implement
// async* generator functions.
@pragma("vm.entry-point")
class _AsyncStarStreamController<T> {
StreamController<T> controller;
Function asyncStarBody;
@ -290,7 +288,6 @@ class _StreamImpl<T> {
Function _generator;
}
@pragma("vm.entry-point")
void _completeOnAsyncReturn(Completer completer, Object value) {
completer.complete(value);
}
@ -300,11 +297,9 @@ void _completeOnAsyncReturn(Completer completer, Object value) {
Object _asyncStackTraceHelper(Function async_op)
native "StackTrace_asyncStackTraceHelper";
@pragma("vm.entry-point")
void _clearAsyncThreadStackTrace()
native "StackTrace_clearAsyncThreadStackTrace";
@pragma("vm.entry-point")
void _setAsyncThreadStackTrace(StackTrace stackTrace)
native "StackTrace_setAsyncThreadStackTrace";

View file

@ -8,7 +8,6 @@
// This function takes care of rehashing of the linked hashmaps in [objects]. We
// do this eagerly after snapshot deserialization.
@pragma("vm.entry-point")
void _rehashObjects(List objects) {
final int length = objects.length;
for (int i = 0; i < length; ++i) {

View file

@ -68,7 +68,6 @@ _registerExtension(String method, ServiceExtensionHandler handler)
native "Developer_registerExtension";
// This code is only invoked when there is no other Dart code on the stack.
@pragma("vm.entry-point", !const bool.fromEnvironment("dart.vm.product"))
_runExtension(
ServiceExtensionHandler handler,
String method,

View file

@ -23,14 +23,12 @@ class Error {
}
class _AssertionError extends Error implements AssertionError {
@pragma("vm.entry-point")
_AssertionError._create(
this._failedAssertion, this._url, this._line, this._column, this.message);
// AssertionError_throwNew in errors.cc fishes the assertion source code
// out of the script. It expects a Dart stack frame from class
// _AssertionError. Thus we need a Dart stub that calls the native code.
@pragma("vm.entry-point")
static _throwNew(int assertionStart, int assertionEnd, Object message) {
_doThrowNew(assertionStart, assertionEnd, message);
}
@ -38,7 +36,6 @@ class _AssertionError extends Error implements AssertionError {
static _doThrowNew(int assertionStart, int assertionEnd, Object message)
native "AssertionError_throwNew";
@pragma("vm.entry-point")
static _evaluateAssertion(condition) {
if (identical(condition, true) || identical(condition, false)) {
return condition;
@ -80,7 +77,6 @@ class _AssertionError extends Error implements AssertionError {
}
class _TypeError extends _AssertionError implements TypeError {
@pragma("vm.entry-point")
_TypeError._create(String url, int line, int column, String errorMsg)
: super._create("is assignable", url, line, column, errorMsg);
@ -103,7 +99,6 @@ class _TypeError extends _AssertionError implements TypeError {
}
class _CastError extends Error implements CastError {
@pragma("vm.entry-point")
_CastError._create(this._url, this._line, this._column, this._errorMsg);
// A CastError is allocated by TypeError._throwNew() when dst_name equals
@ -121,7 +116,6 @@ class _CastError extends Error implements CastError {
@patch
class FallThroughError {
@patch
@pragma("vm.entry-point")
FallThroughError._create(String url, int line)
: _url = url,
_line = line;
@ -140,7 +134,6 @@ class FallThroughError {
}
class _InternalError {
@pragma("vm.entry-point")
const _InternalError(this._msg);
String toString() => "InternalError: '${_msg}'";
final String _msg;
@ -162,7 +155,6 @@ class CyclicInitializationError {
@patch
class AbstractClassInstantiationError {
@pragma("vm.entry-point")
AbstractClassInstantiationError._create(
this._className, this._url, this._line);
@ -260,7 +252,6 @@ class NoSuchMethodError {
// _throwNew above, taking a TypeArguments object rather than an unpacked list
// of types, as well as a list of all arguments and a list of names, rather
// than a separate list of positional arguments and a map of named arguments.
@pragma("vm.entry-point")
NoSuchMethodError._withType(
this._receiver,
String memberName,
@ -579,14 +570,12 @@ class NoSuchMethodError {
}
}
@pragma("vm.entry-point")
class _CompileTimeError extends Error {
final String _errorMsg;
_CompileTimeError(this._errorMsg);
String toString() => _errorMsg;
}
@pragma("vm.entry-point")
dynamic _classRangeAssert(int position, dynamic instance, _Type type, int cid,
int lowerLimit, int upperLimit) {
if ((cid < lowerLimit || cid > upperLimit) && instance != null) {
@ -596,7 +585,6 @@ dynamic _classRangeAssert(int position, dynamic instance, _Type type, int cid,
return instance;
}
@pragma("vm.entry-point")
dynamic _classIdEqualsAssert(
int position, dynamic instance, _Type type, int cid, int otherCid) {
if (cid != otherCid && instance != null) {

View file

@ -8,5 +8,4 @@
bool identical(Object a, Object b) native "Identical_comparison";
@patch
@pragma("vm.entry-point")
int identityHashCode(Object object) => object._identityHashCode;

View file

@ -7,11 +7,9 @@
/// Immutable map class for compiler generated map literals.
// TODO(lrn): Extend MapBase with UnmodifiableMapMixin when mixins
// support forwarding const constructors.
@pragma("vm.entry-point")
class _ImmutableMap<K, V> implements Map<K, V> {
final _ImmutableList _kvPairs;
@pragma("vm.entry-point")
const _ImmutableMap._create(_ImmutableList keyValuePairs)
: _kvPairs = keyValuePairs;

View file

@ -68,7 +68,6 @@ final bool is64Bit = _inquireIs64Bit();
bool _inquireIs64Bit() native "Internal_inquireIs64Bit";
@pragma("vm.entry-point")
bool _classRangeCheck(int cid, int lowerLimit, int upperLimit) {
return cid >= lowerLimit && cid <= upperLimit;
}
@ -98,7 +97,6 @@ class Lists {
// function type arguments (may be null). The result is null if both input
// vectors are null or is a newly allocated and canonicalized vector of length
// 'totalLen'.
@pragma("vm.entry-point")
_prependTypeArguments(functionTypeArguments, parentTypeArguments, parentLen,
totalLen) native "Internal_prependTypeArguments";

View file

@ -176,7 +176,6 @@ class _InvocationMirror implements Invocation {
this._positionalArguments, this._namedArguments, this._isSuperInvocation,
[this._delayedTypeArgumentsLen = 0]);
@pragma("vm.entry-point")
static _allocateInvocationMirror(String functionName,
List argumentsDescriptor, List arguments, bool isSuperInvocation,
[int type = null]) {
@ -189,7 +188,6 @@ class _InvocationMirror implements Invocation {
// indicate 0 type arguments, but the actual number of type arguments are
// passed in `delayedTypeArgumentsLen`. If any type arguments are available,
// the type arguments vector will be the first entry in `arguments`.
@pragma("vm.entry-point")
static _allocateInvocationMirrorForClosure(
String functionName,
List argumentsDescriptor,

View file

@ -106,7 +106,6 @@ void _isolateScheduleImmediate(void callback()) {
_pendingImmediateCallback = callback;
}
@pragma("vm.entry-point")
void _runPendingImmediateCallback() {
if (_pendingImmediateCallback != null) {
var callback = _pendingImmediateCallback;
@ -123,7 +122,6 @@ _ImmediateCallback _removePendingImmediateCallback() {
/// The embedder can execute this function to get hold of
/// [_isolateScheduleImmediate] above.
@pragma("vm.entry-point")
Function _getIsolateScheduleImmediateClosure() {
return _isolateScheduleImmediate;
}
@ -154,14 +152,12 @@ class _RawReceivePortImpl implements RawReceivePort {
_get_sendport() native "RawReceivePortImpl_get_sendport";
// Called from the VM to retrieve the handler for a message.
@pragma("vm.entry-point")
static _lookupHandler(int id) {
var result = _handlerMap[id];
return result;
}
// Called from the VM to dispatch to the handler.
@pragma("vm.entry-point")
static void _handleMessage(Function handler, var message) {
// TODO(floitsch): this relies on the fact that any exception aborts the
// VM. Once we have non-fatal global exceptions we need to catch errors
@ -194,7 +190,6 @@ class _RawReceivePortImpl implements RawReceivePort {
class _SendPortImpl implements SendPort {
/*--- public interface ---*/
@pragma("vm.entry-point")
void send(var message) {
_sendInternal(message);
}
@ -224,7 +219,6 @@ typedef _BinaryFunction(Null args, Null message);
* initial message. Defers execution of the entry point until the
* isolate is in the message loop.
*/
@pragma("vm.entry-point")
void _startMainIsolate(Function entryPoint, List<String> args) {
_startIsolate(
null, // no parent port
@ -240,7 +234,6 @@ void _startMainIsolate(Function entryPoint, List<String> args) {
* Takes the real entry point as argument and invokes it with the initial
* message.
*/
@pragma("vm.entry-point")
void _startIsolate(
SendPort parentPort,
Function entryPoint,

View file

@ -46,7 +46,6 @@ class _LibraryPrefix {
var _outstandingLoadRequests = new List<List>();
// Called from the VM when an outstanding load request has finished.
@pragma("vm.entry-point")
_completeDeferredLoads() {
// Determine which outstanding load requests have completed and complete
// their completer (with an error or true). For outstanding load requests

View file

@ -11,7 +11,6 @@ class Map<K, V> {
// The keys are at position 2*n and are already type checked by the parser
// in checked mode.
// The values are at position 2*n+1 and are not yet type checked.
@pragma("vm.entry-point")
factory Map._fromLiteral(List elements) {
var map = new LinkedHashMap<K, V>();
var len = elements.length;

View file

@ -41,7 +41,6 @@ class Object {
static String _toString(obj) native "Object_toString";
@patch
@pragma("vm.entry-point")
dynamic noSuchMethod(Invocation invocation) {
// TODO(regis): Remove temp constructor identifier 'withInvocation'.
throw new NoSuchMethodError.withInvocation(this, invocation);
@ -50,21 +49,16 @@ class Object {
@patch
Type get runtimeType native "Object_runtimeType";
@pragma("vm.entry-point")
static bool _haveSameRuntimeType(a, b) native "Object_haveSameRuntimeType";
// Call this function instead of inlining instanceof, thus collecting
// type feedback and reducing code size of unoptimized code.
@pragma("vm.entry-point")
bool _instanceOf(instantiatorTypeArguments, functionTypeArguments, type)
native "Object_instanceOf";
// Group of functions for implementing fast simple instance of.
@pragma("vm.entry-point")
bool _simpleInstanceOf(type) native "Object_simpleInstanceOf";
@pragma("vm.entry-point")
bool _simpleInstanceOfTrue(type) => true;
@pragma("vm.entry-point")
bool _simpleInstanceOfFalse(type) => false;
// Call this function instead of inlining 'as', thus collecting type

View file

@ -21,12 +21,10 @@ class _ScheduleImmediate {
static _ScheduleImmediateClosure _closure;
}
@pragma("vm.entry-point")
void _setScheduleImmediateClosure(_ScheduleImmediateClosure closure) {
_ScheduleImmediate._closure = closure;
}
@pragma("vm.entry-point")
void _ensureScheduleImmediate() {
_AsyncRun._scheduleImmediate(_startMicrotaskLoop);
}

View file

@ -794,7 +794,6 @@ abstract class _StringBase implements String {
}
// Convert single object to string.
@pragma("vm.entry-point")
static String _interpolateSingle(Object o) {
if (o is String) return o;
final s = o.toString();
@ -809,7 +808,6 @@ abstract class _StringBase implements String {
* into a result string.
* Modifies the input list if it contains non-`String` values.
*/
@pragma("vm.entry-point")
static String _interpolate(final List values) {
final numValues = values.length;
int totalLength = 0;

View file

@ -462,7 +462,6 @@ class _Timer implements Timer {
}
}
@pragma("vm.entry-point")
_setupHooks() {
VMLibraryHooks.timerFactory = _Timer._factory;
}

View file

@ -1,5 +1,4 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
@pragma("vm.entry-point")
// 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.
@ -37,14 +36,12 @@ import 'dart:math' show Random;
@patch
class ByteData implements TypedData {
@patch
@pragma("vm.entry-point")
factory ByteData(int length) {
final list = new Uint8List(length) as _TypedList;
return new _ByteDataView(list, 0, length);
}
// Called directly from C code.
@pragma("vm.entry-point")
factory ByteData._view(_TypedList typedData, int offsetInBytes, int length) {
return new _ByteDataView(typedData, offsetInBytes, length);
}
@ -1903,7 +1900,6 @@ class _ByteBuffer implements ByteBuffer {
_ByteBuffer(this._data);
@pragma("vm.entry-point")
factory _ByteBuffer._New(data) => new _ByteBuffer(data);
// Forward calls to _data.

View file

@ -156,7 +156,7 @@ class ClassSerializationCluster : public SerializationCluster {
s->Write<int32_t>(cls->ptr()->next_field_offset_in_words_);
s->Write<int32_t>(cls->ptr()->type_arguments_field_offset_in_words_);
s->Write<uint16_t>(cls->ptr()->num_type_arguments_);
s->Write<uint16_t>(cls->ptr()->has_pragma_and_num_own_type_arguments_);
s->Write<uint16_t>(cls->ptr()->num_own_type_arguments_);
s->Write<uint16_t>(cls->ptr()->num_native_fields_);
s->WriteTokenPosition(cls->ptr()->token_pos_);
s->Write<uint16_t>(cls->ptr()->state_bits_);
@ -224,7 +224,7 @@ class ClassDeserializationCluster : public DeserializationCluster {
}
cls->ptr()->type_arguments_field_offset_in_words_ = d->Read<int32_t>();
cls->ptr()->num_type_arguments_ = d->Read<uint16_t>();
cls->ptr()->has_pragma_and_num_own_type_arguments_ = d->Read<uint16_t>();
cls->ptr()->num_own_type_arguments_ = d->Read<uint16_t>();
cls->ptr()->num_native_fields_ = d->Read<uint16_t>();
cls->ptr()->token_pos_ = d->ReadTokenPosition();
cls->ptr()->state_bits_ = d->Read<uint16_t>();
@ -260,7 +260,7 @@ class ClassDeserializationCluster : public DeserializationCluster {
cls->ptr()->next_field_offset_in_words_ = d->Read<int32_t>();
cls->ptr()->type_arguments_field_offset_in_words_ = d->Read<int32_t>();
cls->ptr()->num_type_arguments_ = d->Read<uint16_t>();
cls->ptr()->has_pragma_and_num_own_type_arguments_ = d->Read<uint16_t>();
cls->ptr()->num_own_type_arguments_ = d->Read<uint16_t>();
cls->ptr()->num_native_fields_ = d->Read<uint16_t>();
cls->ptr()->token_pos_ = d->ReadTokenPosition();
cls->ptr()->state_bits_ = d->Read<uint16_t>();

View file

@ -1,53 +0,0 @@
# Entry points @pragma annotations
Dart VM precompiler (AOT compiler) performs whole-program optimizations such as
tree shaking in order to decrease size of the resulting compiled apps and
improve their performance. Such optimizations assume that compiler can see the
whole Dart program, and is able to discover and analyze all Dart functions and
members which can be potentially executed at run time. While the Dart code is
fully available for precompiler, native code of the embedder and native methods
are out of reach of the compiler. Such native code can call back to Dart via
native Dart API.
In order to aid precompiler, programmer can explicitly list entry points
(roots) - Dart classes and members which are accessed from native code. Note
that listing entry points is not optional: as long as program defines native
methods which call into Dart, the entry points are required for the correctness
of compilation.
# Pragma annotation
The annotation `@pragma("vm.entry-point", ...)` can be placed on a class or
member to indicate that it may be allocated or invoked directly from native or
VM code. The allowed uses of the annotation are as follows.
## Classes
Any one of the following forms may be attached to a class:
```dart
@pragma("vm.entry-point")
@pragma("vm.entry-point", true/false)
@pragma("vm.entry-point", !const bool.formEnvironment("dart.vm.product"))
class C { ... }
```
If the second parameter is missing, `null` or `true`, the class will be
available for allocation directly from native or VM code.
## Procedures
Any one of the following forms may be attached to a procedure (including
getters, setters and constructors):
```dart
@pragma("vm.entry-point")
@pragma("vm.entry-point", true/false)
@pragma("vm.entry-point", !const bool.formEnvironment("dart.vm.product"))
void foo() { ... }
```
If the second parameter is missing, `null` or `true`, the procedure will
available for lookup and invocation directly from native or VM code. If the
procedure is a *generative* constructor, the enclosing class will also be marked
for allocation from native or VM code.

View file

@ -491,6 +491,46 @@ void Precompiler::PrecompileConstructors() {
}
static Dart_QualifiedFunctionName vm_entry_points[] = {
// Functions
{"dart:async", "::", "_ensureScheduleImmediate"},
{"dart:core", "::", "_completeDeferredLoads"},
{"dart:core", "::", "identityHashCode"},
{"dart:core", "AbstractClassInstantiationError",
"AbstractClassInstantiationError._create"},
{"dart:core", "ArgumentError", "ArgumentError."},
{"dart:core", "ArgumentError", "ArgumentError.value"},
{"dart:core", "CyclicInitializationError", "CyclicInitializationError."},
{"dart:core", "FallThroughError", "FallThroughError._create"},
{"dart:core", "FormatException", "FormatException."},
{"dart:core", "NoSuchMethodError", "NoSuchMethodError._withType"},
{"dart:core", "NullThrownError", "NullThrownError."},
{"dart:core", "OutOfMemoryError", "OutOfMemoryError."},
{"dart:core", "RangeError", "RangeError."},
{"dart:core", "RangeError", "RangeError.range"},
{"dart:core", "StackOverflowError", "StackOverflowError."},
{"dart:core", "UnsupportedError", "UnsupportedError."},
{"dart:core", "_AssertionError", "_AssertionError._create"},
{"dart:core", "_CastError", "_CastError._create"},
{"dart:core", "_InternalError", "_InternalError."},
{"dart:core", "_InvocationMirror", "_allocateInvocationMirror"},
{"dart:core", "_InvocationMirror", "_allocateInvocationMirrorForClosure"},
{"dart:core", "_TypeError", "_TypeError._create"},
{"dart:collection", "::", "_rehashObjects"},
{"dart:isolate", "IsolateSpawnException", "IsolateSpawnException."},
{"dart:isolate", "::", "_runPendingImmediateCallback"},
{"dart:isolate", "::", "_startIsolate"},
{"dart:isolate", "_RawReceivePortImpl", "_handleMessage"},
{"dart:isolate", "_RawReceivePortImpl", "_lookupHandler"},
{"dart:isolate", "_SendPortImpl", "send"},
{"dart:typed_data", "ByteData", "ByteData."},
{"dart:typed_data", "ByteData", "ByteData._view"},
{"dart:typed_data", "_ByteBuffer", "_ByteBuffer._New"},
{"dart:_vmservice", "::", "boot"},
#if !defined(PRODUCT)
{"dart:_vmservice", "::", "_registerIsolate"},
{"dart:developer", "Metrics", "_printMetrics"},
{"dart:developer", "::", "_runExtension"},
#endif // !PRODUCT
// Fields
{"dart:core", "Error", "_stackTrace"},
{"dart:core", "::", "_uriBaseClosure"},
@ -1468,7 +1508,7 @@ void Precompiler::AddInstantiatedClass(const Class& cls) {
}
}
// Adds all values annotated with @pragma('vm.entry-point') as roots.
// Adds all values annotated with @pragma('vm.entry_point') as roots.
void Precompiler::AddAnnotatedRoots() {
auto& lib = Library::Handle(Z);
auto& cls = Class::Handle(isolate()->object_store()->pragma_class());
@ -1481,48 +1521,38 @@ void Precompiler::AddAnnotatedRoots() {
auto& pragma_options_field =
Field::Handle(Z, cls.LookupField(Symbols::options()));
// Local function allows easy reuse of handles above.
auto metadata_defines_entrypoint = [&]() {
bool is_entry_point = false;
for (intptr_t i = 0; i < metadata.Length(); i++) {
pragma = metadata.At(i);
if (pragma.clazz() != isolate()->object_store()->pragma_class()) {
continue;
}
if (Instance::Cast(pragma).GetField(pragma_name_field) !=
Symbols::vm_entry_point().raw()) {
continue;
}
pragma_options = Instance::Cast(pragma).GetField(pragma_options_field);
if (pragma_options.raw() == Bool::null() ||
pragma_options.raw() == Bool::True().raw()) {
is_entry_point = true;
break;
}
}
return is_entry_point;
};
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
if (cls.has_pragma()) {
metadata ^= lib.GetMetadata(cls);
if (metadata_defines_entrypoint()) {
AddInstantiatedClass(cls);
}
}
functions = cls.functions();
for (intptr_t k = 0; k < functions.Length(); k++) {
function ^= functions.At(k);
if (!function.has_pragma()) continue;
metadata ^= lib.GetMetadata(function);
if (metadata.IsNull()) continue;
if (!metadata_defines_entrypoint()) continue;
bool is_entry_point = false;
for (intptr_t i = 0; i < metadata.Length(); i++) {
pragma = metadata.At(i);
if (pragma.clazz() != isolate()->object_store()->pragma_class()) {
continue;
}
if (Instance::Cast(pragma).GetField(pragma_name_field) !=
Symbols::vm_entry_point().raw()) {
continue;
}
pragma_options =
Instance::Cast(pragma).GetField(pragma_options_field);
if (pragma_options.raw() == Bool::null() ||
pragma_options.raw() == Bool::True().raw()) {
is_entry_point = true;
break;
}
}
if (!is_entry_point) continue;
AddFunction(function);
if (function.IsGenerativeConstructor()) {

View file

@ -1633,7 +1633,7 @@ TEST_CASE(IsolateReload_TearOff_Parameter_Count_Mismatch) {
"Tried calling: C.foo()\n"
"Found: C.foo(dynamic) => dynamic\n"
"#0 Object.noSuchMethod "
"(dart:core/runtime/libobject_patch.dart:47:5)\n"
"(dart:core/runtime/libobject_patch.dart:46:5)\n"
"#1 main (file:///test-lib:8:12)";
} else {
error =
@ -1643,7 +1643,7 @@ TEST_CASE(IsolateReload_TearOff_Parameter_Count_Mismatch) {
"Tried calling: C.foo()\n"
"Found: C.foo(dynamic) => dynamic\n"
"#0 Object.noSuchMethod "
"(dart:core-patch/dart:core/object_patch.dart:47)\n"
"(dart:core-patch/dart:core/object_patch.dart:46)\n"
"#1 main (test-lib:8:12)";
}
EXPECT_ERROR(error_handle, error);

View file

@ -1102,17 +1102,7 @@ Class& KernelLoader::LoadClass(const Library& library,
class_helper.ReadUntilIncluding(ClassHelper::kFlags);
if (class_helper.is_enum_class()) klass.set_is_enum_class();
class_helper.ReadUntilExcluding(ClassHelper::kAnnotations);
intptr_t annotation_count = helper_.ReadListLength();
bool has_pragma_annotation = false;
{
String& native_name_unused = String::Handle(Z);
bool is_potential_native_unused = false;
ReadVMAnnotations(annotation_count, &native_name_unused,
&is_potential_native_unused, &has_pragma_annotation);
}
klass.set_has_pragma(has_pragma_annotation);
class_helper.SetJustRead(ClassHelper::kAnnotations);
class_helper.ReadUntilIncluding(ClassHelper::kAnnotations);
class_helper.ReadUntilExcluding(ClassHelper::kTypeParameters);
intptr_t type_parameter_counts =
helper_.ReadListLength(); // read type_parameters list length.
@ -1128,7 +1118,7 @@ Class& KernelLoader::LoadClass(const Library& library,
class_helper.SetJustRead(ClassHelper::kTypeParameters);
}
if ((FLAG_enable_mirrors || has_pragma_annotation) && annotation_count > 0) {
if (FLAG_enable_mirrors && class_helper.annotation_count_ > 0) {
library.AddClassMetadata(klass, toplevel_class, TokenPosition::kNoSource,
class_offset - correction_offset_);
}
@ -1228,16 +1218,6 @@ void KernelLoader::FinishClassLoading(const Class& klass,
intptr_t constructor_offset = helper_.ReaderOffset() - correction_offset_;
ActiveMemberScope active_member_scope(&active_class_, NULL);
ConstructorHelper constructor_helper(&helper_);
constructor_helper.ReadUntilExcluding(ConstructorHelper::kAnnotations);
intptr_t annotation_count = helper_.ReadListLength();
bool has_pragma_annotation;
{
String& native_name_unused = String::Handle();
bool is_potential_native_unused;
ReadVMAnnotations(annotation_count, &native_name_unused,
&is_potential_native_unused, &has_pragma_annotation);
}
constructor_helper.SetJustRead(ConstructorHelper::kAnnotations);
constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction);
const String& name =
@ -1264,7 +1244,6 @@ void KernelLoader::FinishClassLoading(const Class& klass,
functions_.Add(&function);
function.set_kernel_offset(constructor_offset);
function.set_result_type(T.ReceiverType(klass));
function.set_has_pragma(has_pragma_annotation);
FunctionNodeHelper function_node_helper(&helper_);
function_node_helper.ReadUntilExcluding(
@ -1281,8 +1260,7 @@ void KernelLoader::FinishClassLoading(const Class& klass,
constructor_helper.SetJustRead(ConstructorHelper::kFunction);
constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd);
if ((FLAG_enable_mirrors || has_pragma_annotation) &&
annotation_count > 0) {
if (FLAG_enable_mirrors && constructor_helper.annotation_count_ > 0) {
library.AddFunctionMetadata(function, TokenPosition::kNoSource,
constructor_offset);
}
@ -1342,18 +1320,18 @@ void KernelLoader::FinishLoading(const Class& klass) {
//
// Output parameters:
//
// `native_name`: non-null if `@ExternalName(...)` was identified.
// `native_name`: non-null if `ExternalName(<name>)` was identified.
//
// `is_potential_native`: non-null if there may be an `@ExternalName(...)`
// `is_potential_native`: non-null if there may be an `ExternalName`
// annotation and we need to re-try after reading the constants table.
//
// `has_pragma_annotation`: non-null if @pragma(...) was found (no information
// is given on the kind of pragma directive).
//
void KernelLoader::ReadVMAnnotations(intptr_t annotation_count,
String* native_name,
bool* is_potential_native,
bool* has_pragma_annotation) {
void KernelLoader::ReadProcedureAnnotations(intptr_t annotation_count,
String* native_name,
bool* is_potential_native,
bool* has_pragma_annotation) {
*is_potential_native = false;
*has_pragma_annotation = false;
String& detected_name = String::Handle(Z);
@ -1458,8 +1436,8 @@ void KernelLoader::LoadProcedure(const Library& library,
bool is_potential_native;
bool has_pragma_annotation;
const intptr_t annotation_count = helper_.ReadListLength();
ReadVMAnnotations(annotation_count, &native_name, &is_potential_native,
&has_pragma_annotation);
ReadProcedureAnnotations(annotation_count, &native_name, &is_potential_native,
&has_pragma_annotation);
// If this is a potential native, we'll unset is_external in
// AnnotateNativeProcedures instead.
is_external = is_external && native_name.IsNull();

View file

@ -160,10 +160,10 @@ class KernelLoader : public ValueObject {
void AnnotateNativeProcedures(const Array& constant_table);
void LoadNativeExtensionLibraries(const Array& constant_table);
void ReadVMAnnotations(intptr_t annotation_count,
String* native_name,
bool* is_potential_native,
bool* has_pragma_annotation);
void ReadProcedureAnnotations(intptr_t annotation_count,
String* native_name,
bool* is_potential_native,
bool* has_pragma_annotation);
const String& DartSymbolPlain(StringIndex index) {
return translation_helper_.DartSymbolPlain(index);

View file

@ -571,7 +571,6 @@ void Object::InitOnce(Isolate* isolate) {
cls.set_type_arguments_field_offset_in_words(Class::kNoTypeArguments);
cls.set_num_type_arguments(0);
cls.set_num_own_type_arguments(0);
cls.set_has_pragma(false);
cls.set_num_native_fields(0);
cls.InitEmptyFields();
isolate->RegisterClass(cls);
@ -2192,7 +2191,6 @@ RawClass* Class::New() {
result.set_id(FakeObject::kClassId);
result.set_num_type_arguments(0);
result.set_num_own_type_arguments(0);
result.set_has_pragma(false);
result.set_num_native_fields(0);
result.set_state_bits(0);
if ((FakeObject::kClassId < kInstanceCid) ||
@ -2228,24 +2226,10 @@ void Class::set_num_type_arguments(intptr_t value) const {
}
void Class::set_num_own_type_arguments(intptr_t value) const {
if (!Utils::IsUint(kNumOwnTypeArgumentsSize, value)) {
if (!Utils::IsInt(16, value)) {
ReportTooManyTypeArguments(*this);
}
StoreNonPointer(
&raw_ptr()->has_pragma_and_num_own_type_arguments_,
NumOwnTypeArguments::update(
value, raw_ptr()->has_pragma_and_num_own_type_arguments_));
}
void Class::set_has_pragma_and_num_own_type_arguments(uint16_t value) const {
StoreNonPointer(&raw_ptr()->has_pragma_and_num_own_type_arguments_, value);
}
void Class::set_has_pragma(bool value) const {
StoreNonPointer(
&raw_ptr()->has_pragma_and_num_own_type_arguments_,
HasPragmaBit::update(value,
raw_ptr()->has_pragma_and_num_own_type_arguments_));
StoreNonPointer(&raw_ptr()->num_own_type_arguments_, value);
}
// Initialize class fields of type Array with empty array.
@ -3511,7 +3495,6 @@ RawClass* Class::NewCommon(intptr_t index) {
result.set_id(index);
result.set_num_type_arguments(kUnknownNumTypeArguments);
result.set_num_own_type_arguments(kUnknownNumTypeArguments);
result.set_has_pragma(false);
result.set_num_native_fields(0);
result.set_state_bits(0);
result.InitEmptyFields();

View file

@ -1529,21 +1529,8 @@ class Class : public Object {
// functions_hash_table is in use iff there are at least this many functions.
static const intptr_t kFunctionLookupHashTreshold = 16;
enum HasPragmaAndNumOwnTypeArgumentsBits {
kHasPragmaBit = 0,
kNumOwnTypeArgumentsPos = 1,
kNumOwnTypeArgumentsSize = 15
};
class HasPragmaBit : public BitField<uint16_t, bool, kHasPragmaBit, 1> {};
class NumOwnTypeArguments : public BitField<uint16_t,
uint16_t,
kNumOwnTypeArgumentsPos,
kNumOwnTypeArgumentsSize> {};
// Initial value for the cached number of type arguments.
static const intptr_t kUnknownNumTypeArguments =
(1U << kNumOwnTypeArgumentsSize) - 1;
static const intptr_t kUnknownNumTypeArguments = -1;
int16_t num_type_arguments() const { return raw_ptr()->num_type_arguments_; }
void set_num_type_arguments(intptr_t value) const;
@ -1551,22 +1538,11 @@ class Class : public Object {
return OFFSET_OF(RawClass, num_type_arguments_);
}
public:
bool has_pragma() const {
return HasPragmaBit::decode(
raw_ptr()->has_pragma_and_num_own_type_arguments_);
}
void set_has_pragma(bool has_pragma) const;
private:
uint16_t num_own_type_arguments() const {
return NumOwnTypeArguments::decode(
raw_ptr()->has_pragma_and_num_own_type_arguments_);
int16_t num_own_type_arguments() const {
return raw_ptr()->num_own_type_arguments_;
}
void set_num_own_type_arguments(intptr_t value) const;
void set_has_pragma_and_num_own_type_arguments(uint16_t value) const;
// Assigns empty array to all raw class array fields.
void InitEmptyFields();

View file

@ -4006,7 +4006,6 @@ void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) {
method->has_external,
method->has_native, // May change.
current_class(), method->decl_begin_pos));
func.set_has_pragma(IsPragmaAnnotation(method->metadata_pos));
ASSERT(innermost_function().IsNull());
innermost_function_ = func.raw();
@ -4812,7 +4811,6 @@ void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes,
bool is_abstract = false;
TokenPosition declaration_pos =
metadata_pos.IsReal() ? metadata_pos : TokenPos();
const bool is_pragma = IsPragmaAnnotation(metadata_pos);
if (is_patch_source() && IsPatchAnnotation(metadata_pos)) {
is_patch = true;
metadata_pos = TokenPosition::kNoSource;
@ -4861,9 +4859,6 @@ void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes,
cls.set_token_pos(declaration_pos);
}
}
if (is_pragma) {
cls.set_has_pragma(true);
}
ASSERT(!cls.IsNull());
ASSERT(cls.functions() == Object::empty_array().raw());
set_current_class(cls);
@ -5579,12 +5574,8 @@ bool Parser::IsPatchAnnotation(TokenPosition pos) {
}
TokenPosScope saved_pos(this);
SetPosition(pos);
while (CurrentToken() == Token::kAT) {
ConsumeToken();
if (IsSymbol(Symbols::Patch())) return true;
SkipOneMetadata();
}
return false;
ExpectToken(Token::kAT);
return IsSymbol(Symbols::Patch());
}
bool Parser::IsPragmaAnnotation(TokenPosition pos) {
@ -5593,27 +5584,8 @@ bool Parser::IsPragmaAnnotation(TokenPosition pos) {
}
TokenPosScope saved_pos(this);
SetPosition(pos);
while (CurrentToken() == Token::kAT) {
ConsumeToken();
if (IsSymbol(Symbols::Pragma())) return true;
SkipOneMetadata();
}
return false;
}
void Parser::SkipOneMetadata() {
ExpectIdentifier("identifier expected");
if (CurrentToken() == Token::kPERIOD) {
ConsumeToken();
ExpectIdentifier("identifier expected");
if (CurrentToken() == Token::kPERIOD) {
ConsumeToken();
ExpectIdentifier("identifier expected");
}
}
if (CurrentToken() == Token::kLPAREN) {
SkipToMatchingParenthesis();
}
ExpectToken(Token::kAT);
return IsSymbol(Symbols::Pragma());
}
TokenPosition Parser::SkipMetadata() {
@ -5623,7 +5595,18 @@ TokenPosition Parser::SkipMetadata() {
TokenPosition metadata_pos = TokenPos();
while (CurrentToken() == Token::kAT) {
ConsumeToken();
SkipOneMetadata();
ExpectIdentifier("identifier expected");
if (CurrentToken() == Token::kPERIOD) {
ConsumeToken();
ExpectIdentifier("identifier expected");
if (CurrentToken() == Token::kPERIOD) {
ConsumeToken();
ExpectIdentifier("identifier expected");
}
}
if (CurrentToken() == Token::kLPAREN) {
SkipToMatchingParenthesis();
}
}
return metadata_pos;
}

View file

@ -412,7 +412,6 @@ class Parser : public ValueObject {
void SkipToMatching();
void SkipToMatchingParenthesis();
void SkipBlock();
void SkipOneMetadata();
TokenPosition SkipMetadata();
bool IsPatchAnnotation(TokenPosition pos);
bool IsPragmaAnnotation(TokenPosition pos);

View file

@ -789,12 +789,8 @@ class RawClass : public RawObject {
int32_t next_field_offset_in_words_; // Offset of the next instance field.
classid_t id_; // Class Id, also index in the class table.
int16_t num_type_arguments_; // Number of type arguments in flattened vector.
// Bitfields with number of non-overlapping type arguments and 'has_pragma'
// bit.
uint16_t has_pragma_and_num_own_type_arguments_;
uint16_t num_native_fields_;
int16_t num_own_type_arguments_; // Number of non-overlapping type arguments.
uint16_t num_native_fields_; // Number of native fields in class.
uint16_t state_bits_;
NOT_IN_PRECOMPILED(intptr_t kernel_offset_);

View file

@ -58,7 +58,7 @@ RawClass* Class::ReadFrom(SnapshotReader* reader,
}
cls.set_type_arguments_field_offset_in_words(reader->Read<int32_t>());
cls.set_num_type_arguments(reader->Read<int16_t>());
cls.set_has_pragma_and_num_own_type_arguments(reader->Read<int16_t>());
cls.set_num_own_type_arguments(reader->Read<int16_t>());
cls.set_num_native_fields(reader->Read<uint16_t>());
cls.set_token_pos(TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
cls.set_state_bits(reader->Read<uint16_t>());
@ -114,7 +114,7 @@ void RawClass::WriteTo(SnapshotWriter* writer,
}
writer->Write<int32_t>(ptr()->type_arguments_field_offset_in_words_);
writer->Write<uint16_t>(ptr()->num_type_arguments_);
writer->Write<uint16_t>(ptr()->has_pragma_and_num_own_type_arguments_);
writer->Write<uint16_t>(ptr()->num_own_type_arguments_);
writer->Write<uint16_t>(ptr()->num_native_fields_);
writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
writer->Write<uint16_t>(ptr()->state_bits_);

View file

@ -458,7 +458,7 @@ class ObjectPointerVisitor;
V(GrowRegExpStack, "_growRegExpStack") \
V(DebugProcedureName, ":Eval") \
V(DebugClassName, "#DebugClass") \
V(vm_entry_point, "vm.entry-point")
V(vm_entry_point, "vm.entry_point")
// Contains a list of frequently used strings in a canonicalized form. This
// list is kept in the vm_isolate in order to share the copy across isolates

View file

@ -46,7 +46,6 @@ part of dart.cli;
*/
external void _waitForEvent(int timeoutMillis);
@pragma("vm.entry-point")
void Function(int) _getWaitForEvent() => _waitForEvent;
// This should be set from C++ code by the embedder to wire up waitFor() to the

View file

@ -248,7 +248,7 @@ const Object proxy = const _Proxy();
* function foo is annotated with a pragma 'other-pragma' specific to OtherTool.
*
*/
@pragma('vm.entry-point')
@pragma('vm.entry_point')
class pragma {
/**
* The name of the hint.

View file

@ -116,8 +116,6 @@ class CastError extends Error {}
* Error thrown when attempting to throw [:null:].
*/
class NullThrownError extends Error {
@pragma("vm.entry-point")
NullThrownError();
String toString() => "Throw of null.";
}
@ -141,7 +139,6 @@ class ArgumentError extends Error {
* If the `message` is not a [String], it is assumed to be a value instead
* of a message.
*/
@pragma("vm.entry-point")
ArgumentError([this.message])
: invalidValue = null,
_hasValue = false,
@ -160,7 +157,6 @@ class ArgumentError extends Error {
* names differ from the interface, it might be more useful to use the
* interface method's argument name (or just rename arguments to match).
*/
@pragma("vm.entry-point")
ArgumentError.value(value, [this.name, this.message])
: invalidValue = value,
_hasValue = true;
@ -206,7 +202,6 @@ class RangeError extends ArgumentError {
/**
* Create a new [RangeError] with the given [message].
*/
@pragma("vm.entry-point")
RangeError(var message)
: start = null,
end = null,
@ -239,7 +234,6 @@ class RangeError extends ArgumentError {
* invalid value, and the [message] can override the default error
* description.
*/
@pragma("vm.entry-point")
RangeError.range(num invalidValue, int minValue, int maxValue,
[String name, String message])
: start = minValue,
@ -417,7 +411,6 @@ class IndexError extends ArgumentError implements RangeError {
*/
class FallThroughError extends Error {
FallThroughError();
@pragma("vm.entry-point")
external FallThroughError._create(String url, int line);
external String toString();
@ -488,7 +481,6 @@ class NoSuchMethodError extends Error {
*/
class UnsupportedError extends Error {
final String message;
@pragma("vm.entry-point")
UnsupportedError(this.message);
String toString() => "Unsupported operation: $message";
}
@ -546,7 +538,6 @@ class ConcurrentModificationError extends Error {
}
class OutOfMemoryError implements Error {
@pragma("vm.entry-point")
const OutOfMemoryError();
String toString() => "Out of Memory";
@ -554,7 +545,6 @@ class OutOfMemoryError implements Error {
}
class StackOverflowError implements Error {
@pragma("vm.entry-point")
const StackOverflowError();
String toString() => "Stack Overflow";
@ -570,7 +560,6 @@ class StackOverflowError implements Error {
*/
class CyclicInitializationError extends Error {
final String variableName;
@pragma("vm.entry-point")
CyclicInitializationError([this.variableName]);
String toString() => variableName == null
? "Reading static variable during its initialization"

View file

@ -74,7 +74,6 @@ class FormatException implements Exception {
* Optionally also supply the actual [source] with the incorrect format,
* and the [offset] in the format where a problem was detected.
*/
@pragma("vm.entry-point")
const FormatException([this.message = "", this.source, this.offset]);
/**

View file

@ -18,5 +18,4 @@ external bool identical(Object a, Object b);
*
* This hash code is compatible with [identical].
*/
@pragma("vm.entry-point")
external int identityHashCode(Object object);

View file

@ -104,7 +104,6 @@ class Object {
*
* The default behavior is to throw a [NoSuchMethodError].
*/
@pragma("vm.entry-point")
external dynamic noSuchMethod(Invocation invocation);
/**

View file

@ -144,7 +144,6 @@ class Metrics {
}
// ignore: unused_element, called from native code
@pragma("vm.entry-point", !const bool.fromEnvironment("dart.vm.product"))
static String _printMetrics() {
var metrics = [];
for (var metric in _metrics.values) {

View file

@ -64,7 +64,6 @@ class OSError {
final int errorCode;
/** Creates an OSError object from a message and an errorCode. */
@pragma("vm.entry-point")
const OSError([this.message = "", this.errorCode = noErrorCode]);
/** Converts an OSError object to a string representation. */

View file

@ -126,7 +126,6 @@ abstract class Directory implements FileSystemEntity {
* If [path] is an absolute path, it will be immune to changes to the
* current working directory.
*/
@pragma("vm.entry-point")
factory Directory(String path) {
final IOOverrides overrides = IOOverrides.current;
if (overrides == null) {

View file

@ -247,7 +247,6 @@ abstract class File implements FileSystemEntity {
* If [path] is an absolute path, it will be immune to changes to the
* current working directory.
*/
@pragma("vm.entry-point")
factory File(String path) {
final IOOverrides overrides = IOOverrides.current;
if (overrides == null) {
@ -980,7 +979,6 @@ class FileSystemException implements IOException {
* [message], optional file system path [path] and optional OS error
* [osError].
*/
@pragma("vm.entry-point")
const FileSystemException([this.message = "", this.path = "", this.osError]);
String toString() {

View file

@ -12,7 +12,6 @@ abstract class Link implements FileSystemEntity {
/**
* Creates a Link object.
*/
@pragma("vm.entry-point")
factory Link(String path) {
final IOOverrides overrides = IOOverrides.current;
if (overrides == null) {

View file

@ -19,6 +19,5 @@ abstract class _Namespace {
// If it is not set up by the embedder, relative paths will be resolved
// relative to the process's current working directory and absolute paths will
// be left relative to the file system root.
@pragma("vm.entry-point")
external static void _setupNamespace(var namespace);
}

View file

@ -378,7 +378,6 @@ abstract class RawSecureSocket implements RawSocket {
* get the fields of the certificate.
*/
abstract class X509Certificate {
@pragma("vm.entry-point")
external factory X509Certificate._();
/// The DER encoded bytes of the certificate.
@ -1257,7 +1256,6 @@ class TlsException implements IOException {
final String message;
final OSError osError;
@pragma("vm.entry-point")
const TlsException([String message = "", OSError osError = null])
: this._("TlsException", message, osError);
@ -1283,7 +1281,6 @@ class TlsException implements IOException {
* a secure network connection.
*/
class HandshakeException extends TlsException {
@pragma("vm.entry-point")
const HandshakeException([String message = "", OSError osError = null])
: super._("HandshakeException", message, osError);
}
@ -1294,7 +1291,6 @@ class HandshakeException extends TlsException {
* certificate.
*/
class CertificateException extends TlsException {
@pragma("vm.entry-point")
const CertificateException([String message = "", OSError osError = null])
: super._("CertificateException", message, osError);
}

View file

@ -26,7 +26,6 @@ part "capability.dart";
class IsolateSpawnException implements Exception {
/** Error message reported by the spawn operation. */
final String message;
@pragma("vm.entry-point")
IsolateSpawnException(this.message);
String toString() => "IsolateSpawnException: $message";
}

View file

@ -455,7 +455,6 @@ abstract class ByteData implements TypedData {
* Creates a [ByteData] of the specified length (in elements), all of
* whose bytes are initially zero.
*/
@pragma("vm.entry-point")
external factory ByteData(int length);
/**

View file

@ -696,13 +696,11 @@ class VMService extends MessageRouter {
}
}
@pragma("vm.entry-point")
RawReceivePort boot() {
// Return the port we expect isolate control messages on.
return isolateControlPort;
}
@pragma("vm.entry-point", !const bool.fromEnvironment("dart.vm.product"))
void _registerIsolate(int port_id, SendPort sp, String name) {
var service = new VMService();
service.runningIsolates.isolateStartup(port_id, sp, name);

View file

@ -41,6 +41,8 @@ void main(List<String> args) {
'$buildDir/gen/runtime/bin/precompiler_entry_points.json',
'--entry-points',
'pkg/vm/lib/transformations/type_flow/entry_points_extra.json',
'--entry-points',
'pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json',
scriptPath,
];
runSync("pkg/vm/tool/gen_kernel${Platform.isWindows ? '.bat' : ''}", args);

View file

@ -1036,6 +1036,8 @@ abstract class VMKernelCompilerMixin {
'${_configuration.buildDirectory}/gen/runtime/bin/precompiler_entry_points.json',
'--entry-points',
'${pkgVmDir}/lib/transformations/type_flow/entry_points_extra.json',
'--entry-points',
'${pkgVmDir}/lib/transformations/type_flow/entry_points_extra_standalone.json',
]);
}