Version 2.14.0-132.0.dev
Merge commit '269828ed34b7f2b3406941d5c438a853fe01864f' into 'dev'
diff --git a/DEPS b/DEPS
index c6d7fe8..4c1a614 100644
--- a/DEPS
+++ b/DEPS
@@ -45,7 +45,7 @@
# hashes. It requires access to the dart-build-access group, which EngProd
# has.
"co19_rev": "055b5c984613ec1b8ef76516db3ea99fee63acb9",
- "co19_2_rev": "f7f583366396cb1457e58c9bfb6d6e53dc21d741",
+ "co19_2_rev": "1c2e425f461bfae7de6db7014fc44a58fc72b4a8",
# The internal benchmarks to use. See go/dart-benchmarks-internal
"benchmarks_internal_rev": "076df10d9b77af337f2d8029725787155eb1cd52",
diff --git a/pkg/dartdev/lib/src/templates/server_shelf.dart b/pkg/dartdev/lib/src/templates/server_shelf.dart
index fcd674f..97794bb 100644
--- a/pkg/dartdev/lib/src/templates/server_shelf.dart
+++ b/pkg/dartdev/lib/src/templates/server_shelf.dart
@@ -149,22 +149,22 @@
# Resolve app dependencies.
WORKDIR /app
-COPY pubspec.* .
+COPY pubspec.* ./
RUN dart pub get
# Copy app source code (except anything in .dockerignore) and AOT compile app.
COPY . .
-RUN dart compile exe bin/server.dart -o /server
+RUN dart compile exe bin/server.dart -o bin/server
# Build minimal serving image from AOT-compiled `/server`
# and the pre-built AOT-runtime in the `/runtime/` directory of the base image.
FROM scratch
COPY --from=build /runtime/ /
-COPY --from=build /server /bin/
+COPY --from=build /app/bin/server /app/bin/
# Start server.
EXPOSE 8080
-CMD ["/bin/server"]
+CMD ["/app/bin/server"]
''';
final String _dockerignore = r'''
diff --git a/runtime/platform/assert.h b/runtime/platform/assert.h
index c4155d0..bdf73c5 100644
--- a/runtime/platform/assert.h
+++ b/runtime/platform/assert.h
@@ -339,7 +339,15 @@
#define EXPECT_NULLPTR(ptr) dart::Expect(__FILE__, __LINE__).Null((ptr))
-#define FAIL(error) dart::Expect(__FILE__, __LINE__).Fail("%s", error)
+#if defined(_MSC_VER)
+#define FAIL(format, ...) \
+ dart::Expect(__FILE__, __LINE__).Fail(format, __VA_ARGS__);
+#else
+#define FAIL(format, ...) \
+ dart::Expect(__FILE__, __LINE__).Fail(format, ##__VA_ARGS__);
+#endif
+
+// Leaving old non-varargs versions to avoid having to rewrite all uses.
#define FAIL1(format, p1) dart::Expect(__FILE__, __LINE__).Fail(format, (p1))
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index dd57f81..ece6a7e 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1109,14 +1109,13 @@
Function& func = Function::Handle(d->zone());
for (intptr_t i = start_index_; i < stop_index_; i++) {
func ^= refs.At(i);
- ASSERT(func.ptr()->untag()->code()->IsCode());
- if (!Code::IsUnknownDartCode(func.ptr()->untag()->code())) {
- uword entry_point =
- func.ptr()->untag()->code()->untag()->entry_point_;
+ auto const code = func.ptr()->untag()->code();
+ ASSERT(code->IsCode());
+ if (!Code::IsUnknownDartCode(code)) {
+ uword entry_point = code->untag()->entry_point_;
ASSERT(entry_point != 0);
func.ptr()->untag()->entry_point_ = entry_point;
- uword unchecked_entry_point =
- func.ptr()->untag()->code()->untag()->unchecked_entry_point_;
+ uword unchecked_entry_point = code->untag()->unchecked_entry_point_;
ASSERT(unchecked_entry_point != 0);
func.ptr()->untag()->unchecked_entry_point_ = unchecked_entry_point;
}
@@ -1222,7 +1221,7 @@
static_cast<ContextScopePtr>(d->ReadRef());
}
data->untag()->parent_function_ = static_cast<FunctionPtr>(d->ReadRef());
- data->untag()->closure_ = static_cast<InstancePtr>(d->ReadRef());
+ data->untag()->closure_ = static_cast<ClosurePtr>(d->ReadRef());
data->untag()->default_type_arguments_kind_ =
static_cast<ClosureData::DefaultTypeArgumentsKind>(d->ReadUnsigned());
}
@@ -4464,8 +4463,29 @@
Closure::InstanceSize(),
primary && is_canonical());
ReadFromTo(closure);
+#if defined(DART_PRECOMPILED_RUNTIME)
+ closure->untag()->entry_point_ = 0;
+#endif
}
}
+
+ void PostLoad(Deserializer* d, const Array& refs, bool primary) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ // We only cache the entry point in bare instructions mode (as we need
+ // to load the function anyway otherwise).
+ if (d->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions) {
+ auto& closure = Closure::Handle(d->zone());
+ auto& func = Function::Handle(d->zone());
+ for (intptr_t i = start_index_; i < stop_index_; i++) {
+ closure ^= refs.At(i);
+ func = closure.function();
+ uword entry_point = func.entry_point();
+ ASSERT(entry_point != 0);
+ closure.ptr()->untag()->entry_point_ = entry_point;
+ }
+ }
+#endif
+ }
};
#if !defined(DART_PRECOMPILED_RUNTIME)
@@ -6121,6 +6141,20 @@
uword unchecked_entry_point = code->untag()->unchecked_entry_point_;
ASSERT(unchecked_entry_point != 0);
func->untag()->unchecked_entry_point_ = unchecked_entry_point;
+#if defined(DART_PRECOMPILED_RUNTIME)
+ if (FLAG_use_bare_instructions &&
+ func->untag()->data()->IsHeapObject() &&
+ func->untag()->data()->IsClosureData()) {
+ // For closure functions in bare instructions mode, also update the
+ // cache inside the static implicit closure object, if any.
+ auto data = static_cast<ClosureDataPtr>(func->untag()->data());
+ if (data->untag()->closure() != Closure::null()) {
+ // Closure functions only have one entry point.
+ ASSERT_EQUAL(entry_point, unchecked_entry_point);
+ data->untag()->closure()->untag()->entry_point_ = entry_point;
+ }
+ }
+#endif
}
if (!FLAG_use_bare_instructions) {
code->untag()->object_pool_ = static_cast<ObjectPoolPtr>(d->ReadRef());
@@ -7064,48 +7098,57 @@
GrowableArray<SerializationCluster*> clusters;
// The order that PostLoad runs matters for some classes because of
- // assumptions during canonicalization of some classes about what is already
- // canonical. Explicitly place these clusters first, then add the rest
- // ordered by class id.
-#define ADD_NEXT(cid) \
+ // assumptions during canonicalization, read filling, or post-load filling of
+ // some classes about what has already been read and/or canonicalized.
+ // Explicitly add these clusters first, then add the rest ordered by class id.
+#define ADD_CANONICAL_NEXT(cid) \
if (auto const cluster = canonical_clusters_by_cid_[cid]) { \
clusters.Add(cluster); \
canonical_clusters_by_cid_[cid] = nullptr; \
}
- ADD_NEXT(kOneByteStringCid)
- ADD_NEXT(kTwoByteStringCid)
- ADD_NEXT(kMintCid)
- ADD_NEXT(kDoubleCid)
- ADD_NEXT(kTypeParameterCid)
- ADD_NEXT(kTypeCid)
- ADD_NEXT(kTypeArgumentsCid)
- ADD_NEXT(kClosureCid)
-#undef ADD_NEXT
+#define ADD_NON_CANONICAL_NEXT(cid) \
+ if (auto const cluster = clusters_by_cid_[cid]) { \
+ clusters.Add(cluster); \
+ clusters_by_cid_[cid] = nullptr; \
+ }
+ ADD_CANONICAL_NEXT(kOneByteStringCid)
+ ADD_CANONICAL_NEXT(kTwoByteStringCid)
+ ADD_CANONICAL_NEXT(kStringCid)
+ ADD_CANONICAL_NEXT(kMintCid)
+ ADD_CANONICAL_NEXT(kDoubleCid)
+ ADD_CANONICAL_NEXT(kTypeParameterCid)
+ ADD_CANONICAL_NEXT(kTypeCid)
+ ADD_CANONICAL_NEXT(kTypeArgumentsCid)
+ // Code cluster should be deserialized before Function as
+ // FunctionDeserializationCluster::ReadFill uses instructions table
+ // which is filled in CodeDeserializationCluster::ReadFill.
+ ADD_NON_CANONICAL_NEXT(kCodeCid)
+ // The function cluster should be deserialized before any closures, as
+ // PostLoad for closures caches the entry point found in the function.
+ ADD_NON_CANONICAL_NEXT(kFunctionCid)
+ ADD_CANONICAL_NEXT(kClosureCid)
+#undef ADD_CANONICAL_NEXT
+#undef ADD_NON_CANONICAL_NEXT
const intptr_t out_of_order_clusters = clusters.length();
for (intptr_t cid = 0; cid < num_cids_; cid++) {
if (auto const cluster = canonical_clusters_by_cid_[cid]) {
clusters.Add(cluster);
}
}
- // Put these back so they'll show up in PrintSnapshotSizes.
- for (intptr_t i = 0; i < out_of_order_clusters; i++) {
- auto const cluster = clusters.At(i);
- canonical_clusters_by_cid_[cluster->cid()] = cluster;
- }
- // Code cluster should be deserialized before Function as
- // FunctionDeserializationCluster::ReadFill uses instructions table
- // which is filled in CodeDeserializationCluster::ReadFill.
- if (auto const cluster = clusters_by_cid_[kCodeCid]) {
- clusters.Add(cluster);
- clusters_by_cid_[kCodeCid] = nullptr;
- }
for (intptr_t cid = 0; cid < num_cids_; cid++) {
if (auto const cluster = clusters_by_cid_[cid]) {
clusters.Add(clusters_by_cid_[cid]);
}
}
- // Put this back so it'll show up in PrintSnapshotSizes if present.
- clusters_by_cid_[kCodeCid] = code_cluster_;
+ // Put back any taken out temporarily to avoid re-adding them during the loop.
+ for (intptr_t i = 0; i < out_of_order_clusters; i++) {
+ const auto& cluster = clusters.At(i);
+ const intptr_t cid = cluster->cid();
+ auto const cid_clusters =
+ cluster->is_canonical() ? canonical_clusters_by_cid_ : clusters_by_cid_;
+ ASSERT(cid_clusters[cid] == nullptr);
+ cid_clusters[cid] = cluster;
+ }
instructions_table_len_ = PrepareInstructions();
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index ce21bc8..12baaef 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -3973,14 +3973,12 @@
intptr_t type_args_len,
const Array& argument_names,
const InstructionSource& source,
- intptr_t deopt_id,
- Code::EntryKind entry_kind = Code::EntryKind::kNormal)
+ intptr_t deopt_id)
: TemplateDartCall(deopt_id,
type_args_len,
argument_names,
inputs,
- source),
- entry_kind_(entry_kind) {}
+ source) {}
DECLARE_INSTRUCTION(ClosureCall)
@@ -3989,13 +3987,9 @@
virtual bool HasUnknownSideEffects() const { return true; }
- Code::EntryKind entry_kind() const { return entry_kind_; }
-
PRINT_OPERANDS_TO_SUPPORT
private:
- const Code::EntryKind entry_kind_;
-
DISALLOW_COPY_AND_ASSIGN(ClosureCallInstr);
};
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 61558c5..cb66118 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -597,17 +597,21 @@
Array::ZoneHandle(Z, GetArgumentsDescriptor());
__ LoadObject(R4, arguments_descriptor);
- // R4: Arguments descriptor.
- // R0: Function.
ASSERT(locs()->in(0).reg() == R0);
- if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ // R0: Closure with a cached entry point.
+ __ ldr(R2, compiler::FieldAddress(
+ R0, compiler::target::Closure::entry_point_offset()));
+ } else {
+ // R0: Function.
__ ldr(CODE_REG, compiler::FieldAddress(
R0, compiler::target::Function::code_offset()));
+ // Closure functions only have one entry point.
+ __ ldr(R2, compiler::FieldAddress(
+ R0, compiler::target::Function::entry_point_offset()));
}
- __ ldr(R2,
- compiler::FieldAddress(
- R0, compiler::target::Function::entry_point_offset(entry_kind())));
+ // R4: Arguments descriptor array.
// R2: instructions entry point.
if (!FLAG_precompiled_mode) {
// R9: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index da3b618..b4accd0 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -522,17 +522,22 @@
Array::ZoneHandle(Z, GetArgumentsDescriptor());
__ LoadObject(R4, arguments_descriptor);
- // R4: Arguments descriptor.
- // R0: Function.
ASSERT(locs()->in(0).reg() == R0);
- if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ // R0: Closure with a cached entry point.
+ __ LoadFieldFromOffset(R2, R0,
+ compiler::target::Closure::entry_point_offset());
+ } else {
+ // R0: Function.
__ LoadCompressedFieldFromOffset(CODE_REG, R0,
compiler::target::Function::code_offset());
+ // Closure functions only have one entry point.
+ __ LoadFieldFromOffset(R2, R0,
+ compiler::target::Function::entry_point_offset());
}
- __ LoadFieldFromOffset(
- R2, R0, compiler::target::Function::entry_point_offset(entry_kind()));
- // R2: instructions.
+ // R4: Arguments descriptor array.
+ // R2: instructions entry point.
if (!FLAG_precompiled_mode) {
// R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
__ LoadImmediate(R5, 0);
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 4ba570f..ca703b3 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -6593,8 +6593,7 @@
// EBX: Code (compiled code or lazy compile stub).
ASSERT(locs()->in(0).reg() == EAX);
- __ movl(EBX, compiler::FieldAddress(
- EAX, Function::entry_point_offset(entry_kind())));
+ __ movl(EBX, compiler::FieldAddress(EAX, Function::entry_point_offset()));
// EAX: Function.
// EDX: Arguments descriptor array.
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 2dcf90c..02c1790 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -475,16 +475,17 @@
}
void ClosureCallInstr::PrintOperandsTo(BaseTextBuffer* f) const {
- f->AddString(" function=");
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ f->AddString(" closure=");
+ } else {
+ f->AddString(" function=");
+ }
InputAt(InputCount() - 1)->PrintTo(f);
f->Printf("<%" Pd ">", type_args_len());
for (intptr_t i = 0; i < ArgumentCount(); ++i) {
f->AddString(", ");
ArgumentValueAt(i)->PrintTo(f);
}
- if (entry_kind() == Code::EntryKind::kUnchecked) {
- f->AddString(" using unchecked entrypoint");
- }
}
void InstanceCallInstr::PrintOperandsTo(BaseTextBuffer* f) const {
diff --git a/runtime/vm/compiler/backend/il_test.cc b/runtime/vm/compiler/backend/il_test.cc
index 3f70e07..48654fb 100644
--- a/runtime/vm/compiler/backend/il_test.cc
+++ b/runtime/vm/compiler/backend/il_test.cc
@@ -169,7 +169,7 @@
/*expected_stores=*/{"g"});
RunInitializingStoresTest(root_library, "f3", CompilerPass::kJIT,
/*expected_stores=*/
- {"Closure.function"});
+ {"Closure.function", "Closure.entry_point"});
// Note that in JIT mode we lower context allocation in a way that hinders
// removal of initializing moves so there would be some redundant stores of
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 0ca20ae..72e489e 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -6881,20 +6881,23 @@
Array::ZoneHandle(Z, GetArgumentsDescriptor());
__ LoadObject(R10, arguments_descriptor);
- // Function in RAX.
ASSERT(locs()->in(0).reg() == RAX);
- if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ // RAX: Closure with cached entry point.
+ __ movq(RCX, compiler::FieldAddress(
+ RAX, compiler::target::Closure::entry_point_offset()));
+ } else {
+ // RAX: Function.
__ LoadCompressed(
CODE_REG,
compiler::FieldAddress(RAX, compiler::target::Function::code_offset()));
+ // Closure functions only have one entry point.
+ __ movq(RCX, compiler::FieldAddress(
+ RAX, compiler::target::Function::entry_point_offset()));
}
- __ movq(
- RCX,
- compiler::FieldAddress(
- RAX, compiler::target::Function::entry_point_offset(entry_kind())));
- // RAX: Function.
// R10: Arguments descriptor array.
+ // RCX: instructions entry point.
if (!FLAG_precompiled_mode) {
// RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
__ xorq(RBX, RBX);
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 62172d2..5c8dcc8 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -1051,7 +1051,7 @@
call_data->call->AsPolymorphicInstanceCall()) {
entry_kind = instr->entry_kind();
} else if (ClosureCallInstr* instr = call_data->call->AsClosureCall()) {
- entry_kind = instr->entry_kind();
+ // Closure functions only have one entry point.
}
kernel::FlowGraphBuilder builder(
parsed_function, ic_data_array, /* not building var desc */ NULL,
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index a8ea373..ad2dc86 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -81,6 +81,16 @@
static compiler::OperandSize OperandSize(Representation rep);
};
+// The representation for word-sized unboxed fields.
+static constexpr Representation kUnboxedWord =
+ compiler::target::kWordSize == 4 ? kUnboxedInt32 : kUnboxedInt64;
+// The representation for unsigned word-sized unboxed fields.
+//
+// Note: kUnboxedUword is identical to kUnboxedWord until range analysis can
+// handle unsigned 64-bit ranges. This means that range analysis will give
+// signed results for unboxed uword field values.
+static constexpr Representation kUnboxedUword = kUnboxedWord;
+
// 'UnboxedFfiIntPtr' should be able to hold a pointer of the target word-size.
// On a 32-bit platform, it's an unsigned 32-bit int because it should be
// zero-extended to 64-bits, not sign-extended (pointers are inherently
@@ -92,8 +102,7 @@
// The representation which can be used for native pointers. We use signed 32/64
// bit representation to be able to do arithmetic on pointers.
-static constexpr Representation kUnboxedIntPtr =
- compiler::target::kWordSize == 4 ? kUnboxedInt32 : kUnboxedInt64;
+static constexpr Representation kUnboxedIntPtr = kUnboxedWord;
// Location objects are used to connect register allocator and code generator.
// Instruction templates used by code generator have a corresponding
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index c1019e5..a1daab1 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -110,6 +110,15 @@
V(UnhandledException, UntaggedUnhandledException, exception, Dynamic, FINAL) \
V(UnhandledException, UntaggedUnhandledException, stacktrace, Dynamic, FINAL)
+// Only define AOT-only unboxed native slots when in the precompiler. See
+// UNBOXED_NATIVE_SLOTS_LIST for the format.
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
+#define AOT_ONLY_UNBOXED_NATIVE_SLOTS_LIST(V) \
+ V(Closure, UntaggedClosure, entry_point, Uword, FINAL)
+#else
+#define AOT_ONLY_UNBOXED_NATIVE_SLOTS_LIST(V)
+#endif
+
// List of slots that correspond to unboxed fields of native objects in the
// following format:
//
@@ -125,9 +134,14 @@
// that) or like a non-final field.
//
// Note: As the underlying field is unboxed, these slots cannot be nullable.
+//
+// Note: Currently LoadFieldInstr::IsImmutableLengthLoad() assumes that no
+// unboxed slots represent length loads.
#define UNBOXED_NATIVE_SLOTS_LIST(V) \
+ AOT_ONLY_UNBOXED_NATIVE_SLOTS_LIST(V) \
V(ClosureData, UntaggedClosureData, default_type_arguments_kind, Uint8, \
FINAL) \
+ V(Function, UntaggedFunction, entry_point, Uword, FINAL) \
V(Function, UntaggedFunction, kind_tag, Uint32, FINAL) \
V(Function, UntaggedFunction, packed_fields, Uint32, FINAL) \
V(FunctionType, UntaggedFunctionType, packed_fields, Uint32, FINAL) \
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index acfc656..52416d7 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -1106,7 +1106,7 @@
return Drop();
}
auto& closure = Closure::ZoneHandle(Z, Closure::Cast(options).ptr());
- LocalVariable* entry_point_num = MakeTemporary();
+ LocalVariable* entry_point_num = MakeTemporary("entry_point_num");
auto& function_name = String::ZoneHandle(
Z, String::New(function.ToLibNamePrefixedQualifiedCString(), Heap::kOld));
@@ -1123,27 +1123,30 @@
call_hook += Constant(closure);
call_hook += Constant(function_name);
call_hook += LoadLocal(entry_point_num);
- call_hook += Constant(Function::ZoneHandle(Z, closure.function()));
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ call_hook += Constant(closure);
+ } else {
+ call_hook += Constant(Function::ZoneHandle(Z, closure.function()));
+ }
call_hook += ClosureCall(TokenPosition::kNoSource,
/*type_args_len=*/0, /*argument_count=*/3,
/*argument_names=*/Array::ZoneHandle(Z));
- call_hook += Drop(); // result of closure call
- call_hook += Drop(); // entrypoint number
+ call_hook += Drop(); // result of closure call
+ call_hook += DropTemporary(&entry_point_num); // entrypoint number
return call_hook;
}
Fragment BaseFlowGraphBuilder::ClosureCall(TokenPosition position,
intptr_t type_args_len,
intptr_t argument_count,
- const Array& argument_names,
- bool is_statically_checked) {
- const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0) + 1;
+ const Array& argument_names) {
+ const intptr_t total_count =
+ (type_args_len > 0 ? 1 : 0) + argument_count +
+ /*closure (bare instructions) or function (otherwise)*/ 1;
InputsArray* arguments = GetArguments(total_count);
- ClosureCallInstr* call = new (Z)
- ClosureCallInstr(arguments, type_args_len, argument_names,
- InstructionSource(position), GetNextDeoptId(),
- is_statically_checked ? Code::EntryKind::kUnchecked
- : Code::EntryKind::kNormal);
+ ClosureCallInstr* call =
+ new (Z) ClosureCallInstr(arguments, type_args_len, argument_names,
+ InstructionSource(position), GetNextDeoptId());
Push(call);
return Fragment(call);
}
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index e3948fc..b2d1cfe 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -402,13 +402,13 @@
Fragment BuildEntryPointsIntrospection();
// Builds closure call with given number of arguments. Target closure
- // function is taken from top of the stack.
+ // (in bare instructions mode) or closure function (otherwise) is taken from
+ // top of the stack.
// PushArgument instructions should be already added for arguments.
Fragment ClosureCall(TokenPosition position,
intptr_t type_args_len,
intptr_t argument_count,
- const Array& argument_names,
- bool use_unchecked_entry = false);
+ const Array& argument_names);
// Builds StringInterpolate instruction, an equivalent of
// _StringBase._interpolate call.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 93d9ad5..1ff1ed3 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -3215,14 +3215,15 @@
if (is_unchecked_closure_call) {
// Lookup the function in the closure.
instructions += LoadLocal(receiver_temp);
- instructions += LoadNativeField(Slot::Closure_function());
+ if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
+ instructions += LoadNativeField(Slot::Closure_function());
+ }
if (parsed_function()->function().is_debuggable()) {
ASSERT(!parsed_function()->function().is_native());
instructions += DebugStepCheck(position);
}
instructions +=
- B->ClosureCall(position, type_args_len, argument_count, argument_names,
- /*use_unchecked_entry=*/true);
+ B->ClosureCall(position, type_args_len, argument_count, argument_names);
} else if (!direct_call_target->IsNull()) {
// Even if TFA infers a concrete receiver type, the static type of the
// call-site may still be dynamic and we need to call the dynamic invocation
@@ -3303,14 +3304,15 @@
// Lookup the function in the closure.
instructions += LoadLocal(variable);
- instructions += LoadNativeField(Slot::Closure_function());
+ if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
+ instructions += LoadNativeField(Slot::Closure_function());
+ }
if (parsed_function()->function().is_debuggable()) {
ASSERT(!parsed_function()->function().is_native());
instructions += DebugStepCheck(position);
}
instructions +=
- B->ClosureCall(position, type_args_len, argument_count, argument_names,
- /*use_unchecked_entry=*/true);
+ B->ClosureCall(position, type_args_len, argument_count, argument_names);
return instructions;
}
@@ -3365,14 +3367,15 @@
/*clear_temp=*/false);
// Lookup the function in the closure.
instructions += LoadLocal(receiver_temp);
- instructions += LoadNativeField(Slot::Closure_function());
+ if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
+ instructions += LoadNativeField(Slot::Closure_function());
+ }
if (parsed_function()->function().is_debuggable()) {
ASSERT(!parsed_function()->function().is_native());
instructions += DebugStepCheck(position);
}
instructions +=
- B->ClosureCall(position, type_args_len, argument_count, argument_names,
- /*use_unchecked_entry=*/true);
+ B->ClosureCall(position, type_args_len, argument_count, argument_names);
} else {
instructions += InstanceCall(
position, Symbols::DynamicCall(), Token::kILLEGAL, type_args_len,
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 583a636..a12040d 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -2974,10 +2974,11 @@
}
if (is_closure_call) {
- // Lookup the function in the closure.
body += LoadLocal(closure);
- body += LoadNativeField(Slot::Closure_function());
-
+ if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
+ // Lookup the function in the closure.
+ body += LoadNativeField(Slot::Closure_function());
+ }
body += ClosureCall(TokenPosition::kNoSource, descriptor.TypeArgsLen(),
descriptor.Count(), *argument_names);
} else {
diff --git a/runtime/vm/compiler/offsets_extractor.cc b/runtime/vm/compiler/offsets_extractor.cc
index 4c11893..454457d 100644
--- a/runtime/vm/compiler/offsets_extractor.cc
+++ b/runtime/vm/compiler/offsets_extractor.cc
@@ -96,6 +96,10 @@
"_" #Name " = " \
<< Class::Name << ";\n";
+ AOT_OFFSETS_LIST(PRINT_FIELD_OFFSET, PRINT_ARRAY_LAYOUT, PRINT_SIZEOF,
+ PRINT_ARRAY_SIZEOF, PRINT_PAYLOAD_SIZEOF, PRINT_RANGE,
+ PRINT_CONSTANT)
+
#else // defined(DART_PRECOMPILED_RUNTIME)
#define PRINT_FIELD_OFFSET(Class, Name) \
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 48b7da7..8aa7359 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -613,7 +613,8 @@
#define DEFINE_JIT_FIELD(clazz, name) \
word clazz::name() { \
if (FLAG_precompiled_mode) { \
- FATAL1("Use JIT-only field %s in precompiled mode", #clazz "::" #name); \
+ FATAL("Use of JIT-only field %s in precompiled mode", \
+ #clazz "::" #name); \
} \
return clazz##_##name; \
}
@@ -621,8 +622,8 @@
#define DEFINE_JIT_ARRAY(clazz, name) \
word clazz::name(intptr_t index) { \
if (FLAG_precompiled_mode) { \
- FATAL1("Use of JIT-only array %s in precompiled mode", \
- #clazz "::" #name); \
+ FATAL("Use of JIT-only array %s in precompiled mode", \
+ #clazz "::" #name); \
} \
return clazz##_elements_start_offset + index * clazz##_element_size; \
}
@@ -630,8 +631,8 @@
#define DEFINE_JIT_SIZEOF(clazz, name, what) \
word clazz::name() { \
if (FLAG_precompiled_mode) { \
- FATAL1("Use of JIT-only sizeof %s in precompiled mode", \
- #clazz "::" #name); \
+ FATAL("Use of JIT-only sizeof %s in precompiled mode", \
+ #clazz "::" #name); \
} \
return clazz##_##name; \
}
@@ -639,8 +640,8 @@
#define DEFINE_JIT_RANGE(Class, Getter, Type, First, Last, Filter) \
word Class::Getter(Type index) { \
if (FLAG_precompiled_mode) { \
- FATAL1("Use of JIT-only range %s in precompiled mode", \
- #Class "::" #Getter); \
+ FATAL("Use of JIT-only range %s in precompiled mode", \
+ #Class "::" #Getter); \
} \
return Class##_##Getter[static_cast<intptr_t>(index) - \
static_cast<intptr_t>(First)]; \
@@ -659,6 +660,68 @@
#undef DEFINE_JIT_SIZEOF
#undef DEFINE_JIT_RANGE
+#if defined(DART_PRECOMPILER)
+// The following could check FLAG_precompiled_mode for more safety, but that
+// causes problems for defining things like native Slots, where the definition
+// cannot be based on a runtime flag. Instead, we limit the visibility of these
+// definitions using DART_PRECOMPILER.
+
+#define DEFINE_AOT_FIELD(clazz, name) \
+ word clazz::name() { return AOT_##clazz##_##name; }
+
+#define DEFINE_AOT_ARRAY(clazz, name) \
+ word clazz::name(intptr_t index) { \
+ return AOT_##clazz##_elements_start_offset + \
+ index * AOT_##clazz##_element_size; \
+ }
+
+#define DEFINE_AOT_SIZEOF(clazz, name, what) \
+ word clazz::name() { return AOT_##clazz##_##name; }
+
+#define DEFINE_AOT_RANGE(Class, Getter, Type, First, Last, Filter) \
+ word Class::Getter(Type index) { \
+ return AOT_##Class##_##Getter[static_cast<intptr_t>(index) - \
+ static_cast<intptr_t>(First)]; \
+ }
+#else
+#define DEFINE_AOT_FIELD(clazz, name) \
+ word clazz::name() { \
+ FATAL("Use of AOT-only field %s outside of the precompiler", \
+ #clazz "::" #name); \
+ }
+
+#define DEFINE_AOT_ARRAY(clazz, name) \
+ word clazz::name(intptr_t index) { \
+ FATAL("Use of AOT-only array %s outside of the precompiler", \
+ #clazz "::" #name); \
+ }
+
+#define DEFINE_AOT_SIZEOF(clazz, name, what) \
+ word clazz::name() { \
+ FATAL("Use of AOT-only sizeof %s outside of the precompiler", \
+ #clazz "::" #name); \
+ }
+
+#define DEFINE_AOT_RANGE(Class, Getter, Type, First, Last, Filter) \
+ word Class::Getter(Type index) { \
+ FATAL("Use of AOT-only range %s outside of the precompiler", \
+ #Class "::" #Getter); \
+ }
+#endif // defined(DART_PRECOMPILER)
+
+AOT_OFFSETS_LIST(DEFINE_AOT_FIELD,
+ DEFINE_AOT_ARRAY,
+ DEFINE_AOT_SIZEOF,
+ DEFINE_ARRAY_SIZEOF,
+ DEFINE_PAYLOAD_SIZEOF,
+ DEFINE_AOT_RANGE,
+ DEFINE_CONSTANT)
+
+#undef DEFINE_AOT_FIELD
+#undef DEFINE_AOT_ARRAY
+#undef DEFINE_AOT_SIZEOF
+#undef DEFINE_AOT_RANGE
+
#define DEFINE_FIELD(clazz, name) \
word clazz::name() { \
return FLAG_precompiled_mode ? AOT_##clazz##_##name : clazz##_##name; \
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index e389c80..491e59f 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -1301,6 +1301,7 @@
public:
static word context_offset();
static word delayed_type_arguments_offset();
+ static word entry_point_offset();
static word function_offset();
static word function_type_arguments_offset();
static word instantiator_type_arguments_offset();
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index bdd8b3c..91374ad 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -6494,6 +6494,8 @@
#if !defined(PRODUCT)
#if defined(TARGET_ARCH_ARM) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+ 28;
static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
12;
static constexpr dart::compiler::target::word AOT_Array_element_size = 4;
@@ -7000,7 +7002,7 @@
static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 8;
static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 92;
-static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 28;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 32;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
static constexpr dart::compiler::target::word
@@ -7095,6 +7097,8 @@
#endif // defined(TARGET_ARCH_ARM) && !defined(DART_COMPRESSED_POINTERS)
#if defined(TARGET_ARCH_X64) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+ 56;
static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
24;
static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
@@ -7605,7 +7609,7 @@
static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 160;
-static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
@@ -7703,6 +7707,8 @@
#endif // defined(TARGET_ARCH_IA32) && !defined(DART_COMPRESSED_POINTERS)
#if defined(TARGET_ARCH_ARM64) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+ 56;
static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
24;
static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
@@ -8214,7 +8220,7 @@
static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 160;
-static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
@@ -8309,6 +8315,8 @@
#endif // defined(TARGET_ARCH_ARM64) && !defined(DART_COMPRESSED_POINTERS)
#if defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+ 56;
static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
24;
static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
@@ -8819,7 +8827,7 @@
static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 96;
-static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
@@ -8914,6 +8922,8 @@
#endif // defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS)
#if defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+ 56;
static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
24;
static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
@@ -9425,7 +9435,7 @@
static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 96;
-static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
@@ -9522,6 +9532,8 @@
#else // !defined(PRODUCT)
#if defined(TARGET_ARCH_ARM) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+ 28;
static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
12;
static constexpr dart::compiler::target::word AOT_Array_element_size = 4;
@@ -10021,7 +10033,7 @@
static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 8;
static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 80;
-static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 28;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 32;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
static constexpr dart::compiler::target::word
@@ -10116,6 +10128,8 @@
#endif // defined(TARGET_ARCH_ARM) && !defined(DART_COMPRESSED_POINTERS)
#if defined(TARGET_ARCH_X64) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+ 56;
static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
24;
static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
@@ -10619,7 +10633,7 @@
static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 136;
-static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
@@ -10717,6 +10731,8 @@
#endif // defined(TARGET_ARCH_IA32) && !defined(DART_COMPRESSED_POINTERS)
#if defined(TARGET_ARCH_ARM64) && !defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+ 56;
static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
24;
static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
@@ -11221,7 +11237,7 @@
static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 136;
-static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
@@ -11316,6 +11332,8 @@
#endif // defined(TARGET_ARCH_ARM64) && !defined(DART_COMPRESSED_POINTERS)
#if defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+ 56;
static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
24;
static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
@@ -11819,7 +11837,7 @@
static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 88;
-static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
@@ -11914,6 +11932,8 @@
#endif // defined(TARGET_ARCH_X64) && defined(DART_COMPRESSED_POINTERS)
#if defined(TARGET_ARCH_ARM64) && defined(DART_COMPRESSED_POINTERS)
+static constexpr dart::compiler::target::word AOT_Closure_entry_point_offset =
+ 56;
static constexpr dart::compiler::target::word AOT_Array_elements_start_offset =
24;
static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
@@ -12418,7 +12438,7 @@
static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 88;
-static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index 0af1b9e..fe34979 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -37,6 +37,7 @@
//
// COMMON_OFFSETS_LIST is for declarations that are valid in all contexts.
// JIT_OFFSETS_LIST is for declarations that are only valid in JIT mode.
+// AOT_OFFSETS_LIST is for declarations that are only valid in AOT mode.
// A declaration that is not valid in product mode can be wrapped with
// NOT_IN_PRODUCT().
//
@@ -409,4 +410,8 @@
FIELD(Function, usage_counter_offset) \
FIELD(ICData, receivers_static_type_offset)
+#define AOT_OFFSETS_LIST(FIELD, ARRAY, SIZEOF, ARRAY_SIZEOF, PAYLOAD_SIZEOF, \
+ RANGE, CONSTANT) \
+ FIELD(Closure, entry_point_offset)
+
#endif // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_LIST_H_
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index 4dbf99c..7e42bc2 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
#include "vm/compiler/runtime_api.h"
+#include "vm/flags.h"
#include "vm/globals.h"
// For `StubCodeCompiler::GenerateAllocateUnhandledExceptionStub`
@@ -804,6 +805,24 @@
__ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg,
AllocateClosureABI::kResultReg,
Slot::Closure_hash());
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
+ if (FLAG_precompiled_mode) {
+ // Set the closure entry point in precompiled mode, either to the function
+ // entry point in bare instructions mode or to 0 otherwise (to catch
+ // misuse). This overwrites the scratch register, but there are no more
+ // boxed fields.
+ if (FLAG_use_bare_instructions) {
+ __ LoadFromSlot(AllocateClosureABI::kScratchReg,
+ AllocateClosureABI::kFunctionReg,
+ Slot::Function_entry_point());
+ } else {
+ __ LoadImmediate(AllocateClosureABI::kScratchReg, 0);
+ }
+ __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg,
+ AllocateClosureABI::kResultReg,
+ Slot::Closure_entry_point());
+ }
+#endif
// AllocateClosureABI::kResultReg: new object.
__ Ret();
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index cf63124..4a634d4 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -160,6 +160,10 @@
CHECK_FIELD, CHECK_ARRAY, CHECK_SIZEOF, CHECK_ARRAY_SIZEOF,
CHECK_PAYLOAD_SIZEOF, CHECK_RANGE, CHECK_CONSTANT))
+ ONLY_IN_PRECOMPILED(AOT_OFFSETS_LIST(CHECK_FIELD, CHECK_ARRAY, CHECK_SIZEOF,
+ CHECK_ARRAY_SIZEOF, CHECK_PAYLOAD_SIZEOF,
+ CHECK_RANGE, CHECK_CONSTANT))
+
if (!ok) {
FATAL(
"CheckOffsets failed. Try updating offsets by running "
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index da706c5..0834a41 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7266,16 +7266,16 @@
UNREACHABLE();
}
-InstancePtr Function::implicit_static_closure() const {
+ClosurePtr Function::implicit_static_closure() const {
if (IsImplicitStaticClosureFunction()) {
const Object& obj = Object::Handle(untag()->data());
ASSERT(!obj.IsNull());
return ClosureData::Cast(obj).implicit_static_closure();
}
- return Instance::null();
+ return Closure::null();
}
-void Function::set_implicit_static_closure(const Instance& closure) const {
+void Function::set_implicit_static_closure(const Closure& closure) const {
if (IsImplicitStaticClosureFunction()) {
const Object& obj = Object::Handle(untag()->data());
ASSERT(!obj.IsNull());
@@ -9277,30 +9277,30 @@
}
}
-InstancePtr Function::ImplicitStaticClosure() const {
+ClosurePtr Function::ImplicitStaticClosure() const {
ASSERT(IsImplicitStaticClosureFunction());
- if (implicit_static_closure() != Instance::null()) {
+ if (implicit_static_closure() != Closure::null()) {
return implicit_static_closure();
}
auto thread = Thread::Current();
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
- if (implicit_static_closure() != Instance::null()) {
+ if (implicit_static_closure() != Closure::null()) {
return implicit_static_closure();
}
Zone* zone = thread->zone();
const auto& null_context = Context::Handle(zone);
const auto& closure =
- Instance::Handle(zone, Closure::New(Object::null_type_arguments(),
- Object::null_type_arguments(), *this,
- null_context, Heap::kOld));
+ Closure::Handle(zone, Closure::New(Object::null_type_arguments(),
+ Object::null_type_arguments(), *this,
+ null_context, Heap::kOld));
set_implicit_static_closure(closure);
return implicit_static_closure();
}
-InstancePtr Function::ImplicitInstanceClosure(const Instance& receiver) const {
+ClosurePtr Function::ImplicitInstanceClosure(const Instance& receiver) const {
ASSERT(IsImplicitClosureFunction());
Zone* zone = Thread::Current()->zone();
const Context& context = Context::Handle(zone, Context::New(1));
@@ -10267,9 +10267,9 @@
untag()->set_context_scope(value.ptr());
}
-void ClosureData::set_implicit_static_closure(const Instance& closure) const {
+void ClosureData::set_implicit_static_closure(const Closure& closure) const {
ASSERT(!closure.IsNull());
- ASSERT(untag()->closure() == Instance::null());
+ ASSERT(untag()->closure() == Closure::null());
untag()->set_closure<std::memory_order_release>(closure.ptr());
}
@@ -24985,6 +24985,10 @@
result.untag()->set_delayed_type_arguments(delayed_type_arguments.ptr());
result.untag()->set_function(function.ptr());
result.untag()->set_context(context.ptr());
+#if defined(DART_PRECOMPILED_RUNTIME)
+ result.set_entry_point(FLAG_use_bare_instructions ? function.entry_point()
+ : 0);
+#endif
}
return result.ptr();
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index e3189da..4766260 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2836,9 +2836,9 @@
// Return the closure implicitly created for this function.
// If none exists yet, create one and remember it.
- InstancePtr ImplicitStaticClosure() const;
+ ClosurePtr ImplicitStaticClosure() const;
- InstancePtr ImplicitInstanceClosure(const Instance& receiver) const;
+ ClosurePtr ImplicitInstanceClosure(const Instance& receiver) const;
// Returns the target of the implicit closure or null if the target is now
// invalid (e.g., mismatched argument shapes after a reload).
@@ -3771,8 +3771,8 @@
void set_parent_function(const Function& value) const;
FunctionPtr implicit_closure_function() const;
void set_implicit_closure_function(const Function& value) const;
- InstancePtr implicit_static_closure() const;
- void set_implicit_static_closure(const Instance& closure) const;
+ ClosurePtr implicit_static_closure() const;
+ void set_implicit_static_closure(const Closure& closure) const;
ScriptPtr eval_script() const;
void set_eval_script(const Script& value) const;
void set_num_optional_parameters(intptr_t value) const; // Encoded value.
@@ -3823,10 +3823,10 @@
void set_parent_function(const Function& value) const;
#endif
- InstancePtr implicit_static_closure() const {
+ ClosurePtr implicit_static_closure() const {
return untag()->closure<std::memory_order_acquire>();
}
- void set_implicit_static_closure(const Instance& closure) const;
+ void set_implicit_static_closure(const Closure& closure) const;
DefaultTypeArgumentsKind default_type_arguments_kind() const;
void set_default_type_arguments_kind(DefaultTypeArgumentsKind value) const;
@@ -10937,6 +10937,16 @@
class Closure : public Instance {
public:
+#if defined(DART_PRECOMPILED_RUNTIME)
+ uword entry_point() const { return untag()->entry_point_; }
+ void set_entry_point(uword entry_point) const {
+ StoreNonPointer(&untag()->entry_point_, entry_point);
+ }
+ static intptr_t entry_point_offset() {
+ return OFFSET_OF(UntaggedClosure, entry_point_);
+ }
+#endif
+
TypeArgumentsPtr instantiator_type_arguments() const {
return untag()->instantiator_type_arguments();
}
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index e075887..2f404f5 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -497,8 +497,8 @@
Function& old_func = Function::Handle();
String& selector = String::Handle();
Function& new_func = Function::Handle();
- Instance& old_closure = Instance::Handle();
- Instance& new_closure = Instance::Handle();
+ Closure& old_closure = Closure::Handle();
+ Closure& new_closure = Closure::Handle();
for (intptr_t i = 0; i < funcs.Length(); i++) {
old_func ^= funcs.At(i);
if (old_func.is_static() && old_func.HasImplicitClosureFunction()) {
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index ac28bb9..acff79d 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1408,7 +1408,7 @@
COMPRESSED_POINTER_FIELD(FunctionPtr, parent_function)
#endif
// Closure object for static implicit closures.
- COMPRESSED_POINTER_FIELD(InstancePtr, closure)
+ COMPRESSED_POINTER_FIELD(ClosurePtr, closure)
VISIT_TO(closure)
enum class DefaultTypeArgumentsKind : uint8_t {
@@ -1434,6 +1434,7 @@
DefaultTypeArgumentsKind default_type_arguments_kind_;
friend class Function;
+ friend class UnitDeserializationRoots;
};
class UntaggedFfiTrampolineData : public UntaggedObject {
@@ -2720,6 +2721,12 @@
POINTER_FIELD(SmiPtr, hash)
VISIT_TO(hash)
+ // We have an extra word in the object due to alignment rounding, so use it in
+ // bare instructions mode to cache the entry point from the closure function
+ // to avoid an extra redirection on call. Closure functions only have
+ // one entry point, as dynamic calls use dynamic closure call dispatchers.
+ ONLY_IN_PRECOMPILED(uword entry_point_);
+
ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
// Note that instantiator_type_arguments_, function_type_arguments_ and
@@ -2744,6 +2751,8 @@
// Object::empty_type_arguments(), the types in this vector will be passed as
// type arguments to the closure when invoked. In this case there may not be
// any type arguments passed directly (or NSM will be invoked instead).
+
+ friend class UnitDeserializationRoots;
};
class UntaggedNumber : public UntaggedInstance {
diff --git a/tools/VERSION b/tools/VERSION
index ecfba87..b1dbbe1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 131
+PRERELEASE 132
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/utils/application_snapshot.gni b/utils/application_snapshot.gni
index 7ecdf28..51d2b147 100644
--- a/utils/application_snapshot.gni
+++ b/utils/application_snapshot.gni
@@ -145,7 +145,7 @@
dfe = "$_dart_root/pkg/vm/bin/kernel_service.dart"
abs_depfile = rebase_path(depfile)
- abs_output = rebase_path(output, root_build_dir)
+ abs_output = rebase_path(output)
vm_args = [
"--deterministic",