Version 2.18.0-153.0.dev
Merge commit '5380fa5d400852d5ab6da80f69afd5b1892eec24' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 2cf4ffd..17a79a5 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -761,7 +761,9 @@
return UnspecifiedInvalidResult();
},
(externalLibrary) async {
- var element = libraryContext.getLibraryElement(externalLibrary.uri);
+ final uri = externalLibrary.source.uri;
+ // TODO(scheglov) Check if the source is not for library.
+ var element = libraryContext.getLibraryElement(uri);
return LibraryElementResultImpl(element);
},
);
@@ -1528,7 +1530,6 @@
_saltForUnlinked,
_saltForElements,
featureSetProvider,
- externalSummaries: _externalSummaries,
fileContentCache: _fileContentCache,
);
_fileTracker = FileTracker(_logger, _fsState);
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index a14226d..a6763f8 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -87,9 +87,9 @@
/// A library from [SummaryDataStore].
class ExternalLibrary {
- final Uri uri;
+ final InSummarySource source;
- ExternalLibrary._(this.uri);
+ ExternalLibrary._(this.source);
}
/// [FileContentOverlay] is used to temporary override content of files.
@@ -902,15 +902,6 @@
final FeatureSetProvider featureSetProvider;
- /// The optional store with externally provided unlinked and corresponding
- /// linked summaries. These summaries are always added to the store for any
- /// file analysis.
- ///
- /// While walking the file graph, when we reach a file that exists in the
- /// external store, we add a stub [FileState], but don't attempt to read its
- /// content, or its unlinked unit, or imported libraries, etc.
- final SummaryDataStore? externalSummaries;
-
/// Mapping from a URI to the corresponding [FileState].
final Map<Uri, FileState> _uriToFile = {};
@@ -954,7 +945,6 @@
this._saltForUnlinked,
this._saltForElements,
this.featureSetProvider, {
- this.externalSummaries,
required FileContentCache fileContentCache,
}) : _fileContentCache = fileContentCache {
_testView = FileSystemStateTestView(this);
@@ -1041,20 +1031,16 @@
/// without a package name), or we don't know this package. The returned
/// file has the last known state since if was last refreshed.
Either2<FileState?, ExternalLibrary> getFileForUri(Uri uri) {
+ final uriSource = _sourceFactory.forUri2(uri);
+
// If the external store has this URI, create a stub file for it.
// We are given all required unlinked and linked summaries for it.
- final externalSummaries = this.externalSummaries;
- if (externalSummaries != null) {
- String uriStr = uri.toString();
- if (externalSummaries.uriToSummaryPath.containsKey(uriStr)) {
- return Either2.t2(ExternalLibrary._(uri));
- }
+ if (uriSource is InSummarySource) {
+ return Either2.t2(ExternalLibrary._(uriSource));
}
FileState? file = _uriToFile[uri];
if (file == null) {
- Source? uriSource = _sourceFactory.forUri2(uri);
-
// If the URI cannot be resolved, for example because the factory
// does not understand the scheme, return the unresolved file instance.
if (uriSource == null) {
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index aa43b50..67f8fb8 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -2810,6 +2810,10 @@
}
}
+void Assembler::LoadImmediate(Register rd, Immediate value, Condition cond) {
+ LoadImmediate(rd, value.value(), cond);
+}
+
void Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) {
Operand o;
if (Operand::CanHold(value, &o)) {
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 419dca2..00dc85b 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -47,6 +47,16 @@
namespace compiler {
+class Immediate : public ValueObject {
+ public:
+ explicit Immediate(int32_t value) : value_(value) {}
+
+ int32_t value() const { return value_; }
+
+ private:
+ const int32_t value_;
+};
+
// Instruction encoding bits.
enum {
H = 1 << 5, // halfword (or byte)
@@ -803,6 +813,10 @@
void CallCFunction(Address target) { Call(target); }
+ void CallCFunction(Register target, Condition cond = AL) {
+ blx(target, cond);
+ }
+
// Add signed immediate value to rd. May clobber IP.
void AddImmediate(Register rd, int32_t value, Condition cond = AL) {
AddImmediate(rd, rd, value, cond);
@@ -867,6 +881,7 @@
// These three do not clobber IP.
void LoadPatchableImmediate(Register rd, int32_t value, Condition cond = AL);
void LoadDecodableImmediate(Register rd, int32_t value, Condition cond = AL);
+ void LoadImmediate(Register rd, Immediate value, Condition cond = AL);
void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
// These two may clobber IP.
void LoadSImmediate(SRegister sd, float value, Condition cond = AL);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index e11ed94..3e79152 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1790,7 +1790,15 @@
}
void Call(const Code& code) { BranchLink(code); }
- void CallCFunction(Address target) { Call(target); }
+ // Clobbers LR.
+ void CallCFunction(Address target) {
+ Call(target);
+ }
+ void CallCFunction(Register target) {
+#define __ this->
+ CLOBBERS_LR({ blr(target); });
+#undef __
+ }
void AddImmediate(Register dest, int64_t imm) {
AddImmediate(dest, dest, imm);
@@ -2054,6 +2062,9 @@
void LoadUniqueObject(Register dst, const Object& obj);
// Note: the function never clobbers TMP, TMP2 scratch registers.
void LoadImmediate(Register reg, int64_t imm);
+ void LoadImmediate(Register reg, Immediate imm) {
+ LoadImmediate(reg, imm.value());
+ }
void LoadDImmediate(VRegister reg, double immd);
void LoadQImmediate(VRegister reg, simd128_value_t immq);
@@ -2080,6 +2091,9 @@
LoadImmediate(TMP, immediate);
Push(TMP);
}
+ void PushImmediate(Immediate immediate) {
+ PushImmediate(immediate.value());
+ }
void CompareObject(Register reg, const Object& object);
void ExtractClassIdFromTags(Register result, Register tags);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 2ead117..b5f2b99 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -9,6 +9,7 @@
#include "vm/class_id.h"
#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/backend/locations.h"
#include "vm/cpu.h"
#include "vm/instructions.h"
#include "vm/tags.h"
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 48f6a49..b97296c 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -21,6 +21,7 @@
#include "vm/pointer_tagging.h"
namespace dart {
+
namespace compiler {
class Immediate : public ValueObject {
@@ -747,6 +748,10 @@
}
}
+ void LoadImmediate(Register reg, Immediate immediate) {
+ LoadImmediate(reg, immediate.value());
+ }
+
void LoadDImmediate(XmmRegister dst, double value);
void Drop(intptr_t stack_elements);
@@ -874,6 +879,10 @@
void CallCFunction(Address target) { Call(target); }
+ void CallCFunction(Register target) {
+ call(target);
+ }
+
void Jmp(const Code& code);
void J(Condition condition, const Code& code);
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc
index 863adf4..0c1caab 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.cc
+++ b/runtime/vm/compiler/assembler/assembler_riscv.cc
@@ -2719,6 +2719,10 @@
jalr(RA);
}
+void Assembler::Call(Register target) {
+ jalr(target);
+}
+
void Assembler::AddImmediate(Register rd,
Register rs1,
intx_t imm,
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h
index ac1e920..914301b 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.h
+++ b/runtime/vm/compiler/assembler/assembler_riscv.h
@@ -929,9 +929,13 @@
CodeEntryKind entry_kind = CodeEntryKind::kNormal);
void Call(Address target);
+ void Call(Register target);
void Call(const Code& code) { JumpAndLink(code); }
void CallCFunction(Address target) { Call(target); }
+ void CallCFunction(Register target) {
+ Call(target);
+ }
void AddImmediate(Register dest, intx_t imm) {
AddImmediate(dest, dest, imm);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 6680a77..9f3fb6e 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -1246,7 +1246,7 @@
// offset is not yet known and needs therefore relocation to the right place
// before the code can be used.
//
- // The neccessary information for the "linker" (i.e. the relocation
+ // The necessary information for the "linker" (i.e. the relocation
// information) is stored in [UntaggedCode::static_calls_target_table_]: an
// entry of the form
//
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 63528f15..51af8e2 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -752,15 +752,7 @@
SetValue(instr, non_constant_);
}
-void ConstantPropagator::VisitEnterHandleScope(EnterHandleScopeInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
-void ConstantPropagator::VisitExitHandleScope(ExitHandleScopeInstr* instr) {
- // Nothing to do.
-}
-
-void ConstantPropagator::VisitAllocateHandle(AllocateHandleInstr* instr) {
+void ConstantPropagator::VisitCCall(CCallInstr* instr) {
SetValue(instr, non_constant_);
}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 04712ef..32c36ac 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -3606,7 +3606,6 @@
}
}
-
// The assignment to loading units here must match that in
// AssignLoadingUnitsCodeVisitor, which runs after compilation is done.
static intptr_t LoadingUnitOf(Zone* zone, const Function& function) {
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 98a44f1..8e50cc3 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -4,6 +4,7 @@
#include "vm/compiler/backend/il.h"
+#include "platform/assert.h"
#include "vm/bit_vector.h"
#include "vm/bootstrap.h"
#include "vm/compiler/aot/dispatch_table_generator.h"
@@ -6800,101 +6801,6 @@
__ Comment("EmitReturnMovesEnd");
}
-static Location FirstArgumentLocation() {
-#ifdef TARGET_ARCH_IA32
- return Location::StackSlot(0, SPREG);
-#else
- return Location::RegisterLocation(CallingConventions::ArgumentRegisters[0]);
-#endif
-}
-
-LocationSummary* EnterHandleScopeInstr::MakeLocationSummary(
- Zone* zone,
- bool is_optimizing) const {
- LocationSummary* summary =
- new (zone) LocationSummary(zone, /*num_inputs=*/0,
- /*num_temps=*/0, LocationSummary::kCall);
- summary->set_out(0,
- Location::RegisterLocation(CallingConventions::kReturnReg));
- return summary;
-}
-
-void EnterHandleScopeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- ASSERT(kEnterHandleScopeRuntimeEntry.is_leaf());
-
- Location arg_loc = FirstArgumentLocation();
- __ EnterCFrame(arg_loc.IsRegister() ? 0 : compiler::target::kWordSize);
- NoTemporaryAllocator no_temp;
- compiler->EmitMove(arg_loc, Location::RegisterLocation(THR), &no_temp);
- __ CallCFunction(
- compiler::Address(THR, compiler::target::Thread::OffsetFromThread(
- &kEnterHandleScopeRuntimeEntry)));
- __ LeaveCFrame();
-}
-
-LocationSummary* ExitHandleScopeInstr::MakeLocationSummary(
- Zone* zone,
- bool is_optimizing) const {
- LocationSummary* summary =
- new (zone) LocationSummary(zone, /*num_inputs=*/0,
- /*num_temps=*/0, LocationSummary::kCall);
- return summary;
-}
-
-void ExitHandleScopeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- ASSERT(kEnterHandleScopeRuntimeEntry.is_leaf());
-
- Location arg_loc = FirstArgumentLocation();
- __ EnterCFrame(arg_loc.IsRegister() ? 0 : compiler::target::kWordSize);
- NoTemporaryAllocator no_temp;
- compiler->EmitMove(arg_loc, Location::RegisterLocation(THR), &no_temp);
- __ CallCFunction(
- compiler::Address(THR, compiler::target::Thread::OffsetFromThread(
- &kExitHandleScopeRuntimeEntry)));
- __ LeaveCFrame();
-}
-
-LocationSummary* AllocateHandleInstr::MakeLocationSummary(
- Zone* zone,
- bool is_optimizing) const {
- LocationSummary* summary =
- new (zone) LocationSummary(zone, /*num_inputs=*/1,
- /*num_temps=*/0, LocationSummary::kCall);
-
- Location arg_loc = FirstArgumentLocation();
- // Assign input to a register that does not conflict with anything if
- // argument is passed on the stack.
- const Register scope_reg =
- arg_loc.IsStackSlot() ? CallingConventions::kSecondNonArgumentRegister
- : arg_loc.reg();
-
- summary->set_in(kScope, Location::RegisterLocation(scope_reg));
- summary->set_out(0,
- Location::RegisterLocation(CallingConventions::kReturnReg));
- return summary;
-}
-
-Representation AllocateHandleInstr::RequiredInputRepresentation(
- intptr_t idx) const {
- ASSERT(idx == kScope);
- return kUnboxedIntPtr;
-}
-
-void AllocateHandleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- ASSERT(kEnterHandleScopeRuntimeEntry.is_leaf());
-
- Location arg_loc = FirstArgumentLocation();
- __ EnterCFrame(arg_loc.IsRegister() ? 0 : compiler::target::kWordSize);
- if (arg_loc.IsStackSlot()) {
- NoTemporaryAllocator no_temp;
- compiler->EmitMove(arg_loc, locs()->in(kScope), &no_temp);
- }
- __ CallCFunction(
- compiler::Address(THR, compiler::target::Thread::OffsetFromThread(
- &kAllocateHandleRuntimeEntry)));
- __ LeaveCFrame();
-}
-
LocationSummary* RawStoreFieldInstr::MakeLocationSummary(
Zone* zone,
bool is_optimizing) const {
@@ -7049,6 +6955,126 @@
__ MoveRegister(out, THR);
}
+LocationSummary* CCallInstr::MakeLocationSummaryInternal(
+ Zone* zone,
+ const RegList temps) const {
+ LocationSummary* summary =
+ new (zone) LocationSummary(zone, /*num_inputs=*/InputCount(),
+ /*num_temps=*/Utils::CountOneBitsWord(temps),
+ LocationSummary::kNativeLeafCall);
+
+ intptr_t reg_i = 0;
+ for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) {
+ if ((temps & (1 << reg)) != 0) {
+ summary->set_temp(reg_i,
+ Location::RegisterLocation(static_cast<Register>(reg)));
+ reg_i++;
+ }
+ }
+
+ summary->set_in(TargetAddressIndex(),
+ Location::RegisterLocation(
+ CallingConventions::kFirstNonArgumentRegister));
+
+ const auto& argument_locations =
+ native_calling_convention_.argument_locations();
+ for (intptr_t i = 0, n = argument_locations.length(); i < n; ++i) {
+ const auto& argument_location = *argument_locations.At(i);
+ if (argument_location.IsRegisters()) {
+ const auto& reg_location = argument_location.AsRegisters();
+ ASSERT(reg_location.num_regs() == 1);
+ summary->set_in(i, reg_location.AsLocation());
+ } else if (argument_location.IsFpuRegisters()) {
+ UNIMPLEMENTED();
+ } else if (argument_location.IsStack()) {
+ summary->set_in(i, Location::Any());
+ } else {
+ UNIMPLEMENTED();
+ }
+ }
+ const auto& return_location = native_calling_convention_.return_location();
+ ASSERT(return_location.IsRegisters());
+ summary->set_out(0, return_location.AsLocation());
+ return summary;
+}
+
+CCallInstr::CCallInstr(
+ Zone* zone,
+ const compiler::ffi::NativeCallingConvention& native_calling_convention,
+ InputsArray* inputs)
+ : Definition(DeoptId::kNone),
+ zone_(zone),
+ native_calling_convention_(native_calling_convention),
+ inputs_(inputs) {
+#ifdef DEBUG
+ const intptr_t num_inputs =
+ native_calling_convention.argument_locations().length() + 1;
+ ASSERT(num_inputs == inputs->length());
+#endif
+ for (intptr_t i = 0, n = inputs_->length(); i < n; ++i) {
+ SetInputAt(i, (*inputs_)[i]);
+ }
+}
+
+Representation CCallInstr::RequiredInputRepresentation(intptr_t idx) const {
+ if (idx < native_calling_convention_.argument_locations().length()) {
+ const auto& argument_type =
+ native_calling_convention_.argument_locations().At(idx)->payload_type();
+ ASSERT(argument_type.IsExpressibleAsRepresentation());
+ return argument_type.AsRepresentation();
+ }
+ ASSERT(idx == TargetAddressIndex());
+ return kUnboxedFfiIntPtr;
+}
+
+void CCallInstr::EmitParamMoves(FlowGraphCompiler* compiler,
+ Register saved_fp,
+ Register temp0) {
+ if (native_calling_convention_.StackTopInBytes() == 0) {
+ return;
+ }
+
+ ConstantTemporaryAllocator temp_alloc(temp0);
+ compiler::ffi::FrameRebase rebase(zone_, /*old_base=*/FPREG,
+ /*new_base=*/saved_fp,
+ /*stack_delta=*/0);
+
+ __ Comment("EmitParamMoves");
+ const auto& argument_locations =
+ native_calling_convention_.argument_locations();
+ for (intptr_t i = 0, n = argument_locations.length(); i < n; ++i) {
+ const auto& argument_location = *argument_locations.At(i);
+ if (argument_location.IsRegisters()) {
+ const auto& reg_location = argument_location.AsRegisters();
+ ASSERT(reg_location.num_regs() == 1);
+ const Location src_loc = rebase.Rebase(locs()->in(i));
+ const Representation src_rep = RequiredInputRepresentation(i);
+ compiler->EmitMoveToNative(argument_location, src_loc, src_rep,
+ &temp_alloc);
+ } else if (argument_location.IsFpuRegisters()) {
+ UNIMPLEMENTED();
+ } else if (argument_location.IsStack()) {
+ const Location src_loc = rebase.Rebase(locs()->in(i));
+ const Representation src_rep = RequiredInputRepresentation(i);
+ __ Comment("Param %" Pd ": %s %s -> %s", i, src_loc.ToCString(),
+ RepresentationToCString(src_rep),
+ argument_location.ToCString());
+ compiler->EmitMoveToNative(argument_location, src_loc, src_rep,
+ &temp_alloc);
+ } else {
+ UNIMPLEMENTED();
+ }
+ }
+ __ Comment("EmitParamMovesEnd");
+}
+
+Representation CCallInstr::representation() const {
+ const auto& return_type =
+ native_calling_convention_.return_location().payload_type();
+ ASSERT(return_type.IsExpressibleAsRepresentation());
+ return return_type.AsRepresentation();
+}
+
// SIMD
SimdOpInstr::Kind SimdOpInstr::KindForOperator(MethodRecognizer::Kind kind) {
@@ -7206,7 +7232,7 @@
Representation inputs[4];
};
-// Make representaion from type name used by SIMD_OP_LIST.
+// Make representation from type name used by SIMD_OP_LIST.
#define REP(T) (kUnboxed##T)
static const Representation kUnboxedBool = kTagged;
static const Representation kUnboxedInt8 = kUnboxedInt32;
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index c4192ba..9f7562f 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -428,9 +428,7 @@
M(SpecialParameter, kNoGC) \
M(ClosureCall, _) \
M(FfiCall, _) \
- M(EnterHandleScope, kNoGC) \
- M(ExitHandleScope, kNoGC) \
- M(AllocateHandle, kNoGC) \
+ M(CCall, kNoGC) \
M(RawStoreField, kNoGC) \
M(InstanceCall, _) \
M(PolymorphicInstanceCall, _) \
@@ -5349,50 +5347,53 @@
DISALLOW_COPY_AND_ASSIGN(FfiCallInstr);
};
-class EnterHandleScopeInstr : public TemplateDefinition<0, NoThrow> {
+// Has the target address in a register passed as the last input in IL.
+class CCallInstr : public Definition {
public:
- EnterHandleScopeInstr() {}
+ CCallInstr(
+ Zone* zone,
+ const compiler::ffi::NativeCallingConvention& native_calling_convention,
+ InputsArray* inputs);
- DECLARE_INSTRUCTION(EnterHandleScope)
+ DECLARE_INSTRUCTION(CCall)
- virtual Representation representation() const { return kUnboxedIntPtr; }
+ LocationSummary* MakeLocationSummaryInternal(Zone* zone,
+ const RegList temps) const;
+
+ // Input index of the function pointer to invoke.
+ intptr_t TargetAddressIndex() const {
+ return native_calling_convention_.argument_locations().length();
+ }
+
+ virtual intptr_t InputCount() const { return inputs_->length(); }
+ virtual Value* InputAt(intptr_t i) const { return inputs_->At(i); }
+ virtual bool MayThrow() const { return false; }
+
virtual bool ComputeCanDeoptimize() const { return false; }
- virtual bool HasUnknownSideEffects() const { return false; }
+
+ virtual bool HasUnknownSideEffects() const { return true; }
+
+ virtual bool CanCallDart() const { return false; }
+
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const;
+ virtual Representation representation() const;
+
+ void EmitParamMoves(FlowGraphCompiler* compiler,
+ Register saved_fp,
+ Register temp0);
PRINT_OPERANDS_TO_SUPPORT
private:
- DISALLOW_COPY_AND_ASSIGN(EnterHandleScopeInstr);
-};
+ virtual void RawSetInputAt(intptr_t i, Value* value) {
+ (*inputs_)[i] = value;
+ }
-class ExitHandleScopeInstr : public TemplateInstruction<0, NoThrow> {
- public:
- ExitHandleScopeInstr() {}
+ Zone* const zone_;
+ const compiler::ffi::NativeCallingConvention& native_calling_convention_;
+ InputsArray* inputs_;
- DECLARE_INSTRUCTION(ExitHandleScope)
-
- virtual bool ComputeCanDeoptimize() const { return false; }
- virtual bool HasUnknownSideEffects() const { return false; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ExitHandleScopeInstr);
-};
-
-class AllocateHandleInstr : public TemplateDefinition<1, NoThrow> {
- public:
- explicit AllocateHandleInstr(Value* scope) { SetInputAt(kScope, scope); }
-
- enum { kScope = 0 };
-
- DECLARE_INSTRUCTION(AllocateHandle)
-
- virtual Representation RequiredInputRepresentation(intptr_t idx) const;
- virtual Representation representation() const { return kUnboxedIntPtr; }
- virtual bool ComputeCanDeoptimize() const { return false; }
- virtual bool HasUnknownSideEffects() const { return false; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AllocateHandleInstr);
+ DISALLOW_COPY_AND_ASSIGN(CCallInstr);
};
// Populates the untagged base + offset outside the heap with a tagged value.
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 8794fb4..d42f1c2 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1714,6 +1714,33 @@
FunctionEntryInstr::EmitNativeCode(compiler);
}
+#define R(r) (1 << r)
+
+LocationSummary* CCallInstr::MakeLocationSummary(Zone* zone,
+ bool is_optimizing) const {
+ constexpr Register saved_fp = CallingConventions::kSecondNonArgumentRegister;
+ return MakeLocationSummaryInternal(zone, (R(saved_fp)));
+}
+
+#undef R
+
+void CCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const Register saved_fp = locs()->temp(0).reg();
+ const Register temp0 = TMP;
+
+ __ MoveRegister(saved_fp, FPREG);
+
+ const intptr_t frame_space = native_calling_convention_.StackTopInBytes();
+ __ EnterCFrame(frame_space);
+
+ EmitParamMoves(compiler, saved_fp, temp0);
+
+ const Register target_address = locs()->in(TargetAddressIndex()).reg();
+ __ CallCFunction(target_address);
+
+ __ LeaveCFrame();
+}
+
LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 6c1cc4f..2dfcd42 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -1577,6 +1577,41 @@
FunctionEntryInstr::EmitNativeCode(compiler);
}
+#define R(r) (1 << r)
+
+LocationSummary* CCallInstr::MakeLocationSummary(Zone* zone,
+ bool is_optimizing) const {
+ constexpr Register saved_csp = kAbiFirstPreservedCpuReg;
+ ASSERT(IsAbiPreservedRegister(saved_csp));
+ return MakeLocationSummaryInternal(zone, (R(saved_csp)));
+}
+
+#undef R
+
+void CCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const Register saved_fp = TMP2;
+ const Register temp0 = TMP;
+ const Register saved_csp = locs()->temp(0).reg();
+
+ __ MoveRegister(saved_fp, FPREG);
+
+ const intptr_t frame_space = native_calling_convention_.StackTopInBytes();
+ __ EnterCFrame(frame_space);
+ ASSERT(IsAbiPreservedRegister(saved_csp));
+ __ mov(saved_csp, CSP);
+ __ mov(CSP, SP);
+
+ EmitParamMoves(compiler, saved_fp, temp0);
+
+ const Register target_address = locs()->in(TargetAddressIndex()).reg();
+ __ CallCFunction(target_address);
+
+ // We don't use the DartSP, we leave the frame after this immediately.
+ // However, we need set CSP to a 16 byte aligned value far above the SP.
+ __ mov(CSP, saved_csp);
+ __ LeaveCFrame();
+}
+
LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 1915491..1513ce0 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -1248,6 +1248,34 @@
FunctionEntryInstr::EmitNativeCode(compiler);
}
+#define R(r) (1 << r)
+
+LocationSummary* CCallInstr::MakeLocationSummary(Zone* zone,
+ bool is_optimizing) const {
+ constexpr Register saved_fp = CallingConventions::kSecondNonArgumentRegister;
+ constexpr Register temp0 = CallingConventions::kFfiAnyNonAbiRegister;
+ static_assert(saved_fp < temp0, "Unexpected ordering of registers in set.");
+ return MakeLocationSummaryInternal(zone, (R(saved_fp) | R(temp0)));
+}
+
+#undef R
+
+void CCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const Register saved_fp = locs()->temp(0).reg();
+ const Register temp0 = locs()->temp(1).reg();
+
+ __ MoveRegister(saved_fp, FPREG);
+ const intptr_t frame_space = native_calling_convention_.StackTopInBytes();
+ __ EnterCFrame(frame_space);
+
+ EmitParamMoves(compiler, saved_fp, temp0);
+
+ const Register target_address = locs()->in(TargetAddressIndex()).reg();
+ __ CallCFunction(target_address);
+
+ __ LeaveCFrame();
+}
+
static bool CanBeImmediateIndex(Value* value, intptr_t cid) {
ConstantInstr* constant = value->definition()->AsConstant();
if ((constant == NULL) ||
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index f901a37f..8f983bd 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -1286,8 +1286,20 @@
}
}
-void EnterHandleScopeInstr::PrintOperandsTo(BaseTextBuffer* f) const {
- f->AddString("<enter handle scope>");
+void CCallInstr::PrintOperandsTo(BaseTextBuffer* f) const {
+ f->AddString(" target_address=");
+ InputAt(TargetAddressIndex())->PrintTo(f);
+
+ const auto& argument_locations =
+ native_calling_convention_.argument_locations();
+ for (intptr_t i = 0; i < argument_locations.length(); i++) {
+ const auto& arg_location = *argument_locations.At(i);
+ f->AddString(", ");
+ InputAt(i)->PrintTo(f);
+ f->AddString(" (@");
+ arg_location.PrintTo(f);
+ f->AddString(")");
+ }
}
void NativeReturnInstr::PrintOperandsTo(BaseTextBuffer* f) const {
diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc
index 00b0cdb..73580e9 100644
--- a/runtime/vm/compiler/backend/il_riscv.cc
+++ b/runtime/vm/compiler/backend/il_riscv.cc
@@ -1426,13 +1426,7 @@
#define R(r) (1 << r)
-LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
- bool is_optimizing) const {
- LocationSummary* summary = MakeLocationSummaryInternal(
- zone, is_optimizing,
- (R(CallingConventions::kSecondNonArgumentRegister) |
- R(CallingConventions::kFfiAnyNonAbiRegister) | R(CALLEE_SAVED_TEMP2)));
-
+static void RemapA3A4A5(LocationSummary* summary) {
// A3/A4/A5 are unavailable in normal register allocation because they are
// assigned to TMP/TMP2/PP. This assignment is important for reducing code
// size. We can't just override the normal blockage of these registers because
@@ -1450,6 +1444,18 @@
summary->set_in(i, Location::RegisterLocation(T5));
}
}
+}
+
+#define R(r) (1 << r)
+
+LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
+ bool is_optimizing) const {
+ LocationSummary* summary = MakeLocationSummaryInternal(
+ zone, is_optimizing,
+ (R(CallingConventions::kSecondNonArgumentRegister) |
+ R(CallingConventions::kFfiAnyNonAbiRegister) | R(CALLEE_SAVED_TEMP2)));
+
+ RemapA3A4A5(summary);
return summary;
}
@@ -1759,6 +1765,47 @@
FunctionEntryInstr::EmitNativeCode(compiler);
}
+#define R(r) (1 << r)
+
+LocationSummary* CCallInstr::MakeLocationSummary(Zone* zone,
+ bool is_optimizing) const {
+ constexpr Register saved_fp = CallingConventions::kSecondNonArgumentRegister;
+ constexpr Register temp0 = CallingConventions::kFfiAnyNonAbiRegister;
+ static_assert(saved_fp < temp0, "Unexpected ordering of registers in set.");
+ LocationSummary* summary =
+ MakeLocationSummaryInternal(zone, (R(saved_fp) | R(temp0)));
+ RemapA3A4A5(summary);
+ return summary;
+}
+
+#undef R
+
+void CCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const Register saved_fp = locs()->temp(0).reg();
+ const Register temp0 = locs()->temp(1).reg();
+
+ // Beware! Do not use CODE_REG/TMP/TMP2/PP within FfiCallInstr as they are
+ // assigned to A2/A3/A4/A5, which may be in use as argument registers.
+ __ set_constant_pool_allowed(false);
+
+ __ MoveRegister(saved_fp, FPREG);
+
+ const intptr_t frame_space = native_calling_convention_.StackTopInBytes();
+ __ EnterCFrame(frame_space);
+
+ // Also does the remapping A3/A4/A5.
+ EmitParamMoves(compiler, saved_fp, temp0);
+
+ const Register target_address = locs()->in(TargetAddressIndex()).reg();
+ __ CallCFunction(target_address);
+
+ __ LeaveCFrame();
+
+ // PP is a volatile register, so it must be restored even for leaf FFI calls.
+ __ RestorePoolPointer();
+ __ set_constant_pool_allowed(true);
+}
+
LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index b6b58ce..55fc995 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1444,6 +1444,34 @@
FunctionEntryInstr::EmitNativeCode(compiler);
}
+#define R(r) (1 << r)
+
+LocationSummary* CCallInstr::MakeLocationSummary(Zone* zone,
+ bool is_optimizing) const {
+ constexpr Register saved_fp = CallingConventions::kSecondNonArgumentRegister;
+ return MakeLocationSummaryInternal(zone, (R(saved_fp)));
+}
+
+#undef R
+
+void CCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const Register saved_fp = locs()->temp(0).reg();
+ const Register temp0 = TMP;
+
+ // TODO(http://dartbug.com/47778): If we knew whether the stack was aligned
+ // at this point, we could omit having a frame.
+ __ MoveRegister(saved_fp, FPREG);
+
+ const intptr_t frame_space = native_calling_convention_.StackTopInBytes();
+ __ EnterCFrame(frame_space);
+
+ EmitParamMoves(compiler, saved_fp, temp0);
+ const Register target_address = locs()->in(TargetAddressIndex()).reg();
+ __ CallCFunction(target_address);
+
+ __ LeaveCFrame();
+}
+
static bool CanBeImmediateIndex(Value* index, intptr_t cid) {
if (!index->definition()->IsConstant()) return false;
const Object& constant = index->definition()->AsConstant()->value();
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index c9245a5..7d37d1f 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -1876,7 +1876,7 @@
// 1) Populate 'gen' sets with places which are initialized at each basic
// block. Optimize lazy initializer calls within basic block and
- // figure out if there are lazy intializer calls left to optimize.
+ // figure out if there are lazy initializer calls left to optimize.
bool has_lazy_initializer_calls = false;
for (BlockIterator block_it = graph_->reverse_postorder_iterator();
!block_it.Done(); block_it.Advance()) {
@@ -4351,7 +4351,6 @@
if (MayHaveVisibleEffect(current) || current->CanDeoptimize() ||
current == block->last_instruction() || current->IsMaterializeObject() ||
current->IsCheckStackOverflow() || current->IsReachabilityFence() ||
- current->IsEnterHandleScope() || current->IsExitHandleScope() ||
current->IsRawStoreField()) {
return false;
}
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 2ea7890..f6a4dd3 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -311,6 +311,7 @@
INVOKE_PASS(TypePropagation);
INVOKE_PASS(WidenSmiToInt32);
INVOKE_PASS(SelectRepresentations_Final);
+ INVOKE_PASS(CSE);
INVOKE_PASS(TypePropagation);
INVOKE_PASS(TryCatchOptimization);
INVOKE_PASS(EliminateEnvironments);
diff --git a/runtime/vm/compiler/ffi/native_location.cc b/runtime/vm/compiler/ffi/native_location.cc
index ef92266..ca039d3 100644
--- a/runtime/vm/compiler/ffi/native_location.cc
+++ b/runtime/vm/compiler/ffi/native_location.cc
@@ -318,7 +318,12 @@
}
void NativeStackLocation::PrintTo(BaseTextBuffer* f) const {
- f->Printf("S%+" Pd, offset_in_bytes_);
+ if (base_register_ != SPREG) {
+ f->Printf("S(%s)+%" Pd, RegisterNames::RegisterAbiName(base_register_),
+ offset_in_bytes_);
+ } else {
+ f->Printf("S+%" Pd, offset_in_bytes_);
+ }
PrintRepresentations(f, *this);
}
diff --git a/runtime/vm/compiler/ffi/native_type.cc b/runtime/vm/compiler/ffi/native_type.cc
index 6838082..a6cf2e4 100644
--- a/runtime/vm/compiler/ffi/native_type.cc
+++ b/runtime/vm/compiler/ffi/native_type.cc
@@ -8,6 +8,7 @@
#include "platform/globals.h"
#include "vm/class_id.h"
#include "vm/compiler/ffi/abi.h"
+#include "vm/compiler/runtime_api.h"
#include "vm/constants.h"
#include "vm/zone_text_buffer.h"
@@ -583,6 +584,23 @@
Representation rep) {
return *new (zone) NativePrimitiveType(fundamental_rep(rep));
}
+
+const NativeFunctionType* NativeFunctionType::FromUnboxedRepresentation(
+ Zone* zone,
+ intptr_t num_arguments,
+ Representation representation) {
+ const auto& intptr_type =
+ compiler::ffi::NativePrimitiveType::FromUnboxedRepresentation(
+ zone, representation);
+ auto& argument_representations =
+ *new (zone) ZoneGrowableArray<const compiler::ffi::NativeType*>(
+ zone, num_arguments);
+ for (intptr_t i = 0; i < num_arguments; i++) {
+ argument_representations.Add(&intptr_type);
+ }
+ return new (zone)
+ compiler::ffi::NativeFunctionType(argument_representations, intptr_type);
+}
#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
const char* NativeType::ToCString(Zone* zone,
diff --git a/runtime/vm/compiler/ffi/native_type.h b/runtime/vm/compiler/ffi/native_type.h
index a3a03bd..e85f091 100644
--- a/runtime/vm/compiler/ffi/native_type.h
+++ b/runtime/vm/compiler/ffi/native_type.h
@@ -404,6 +404,13 @@
const NativeType& return_type)
: argument_types_(argument_types), return_type_(return_type) {}
+#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(FFI_UNIT_TESTS)
+ static const NativeFunctionType* FromUnboxedRepresentation(
+ Zone* zone,
+ intptr_t num_arguments,
+ Representation representation);
+#endif
+
const NativeTypes& argument_types() const { return argument_types_; }
const NativeType& return_type() const { return return_type_; }
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index fda2a9b..8a20c37 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -31,6 +31,7 @@
#include "vm/object_store.h"
#include "vm/report.h"
#include "vm/resolver.h"
+#include "vm/runtime_entry.h"
#include "vm/scopes.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
@@ -407,6 +408,37 @@
return body;
}
+Fragment FlowGraphBuilder::CCall(
+ const compiler::ffi::NativeCallingConvention& native_calling_convention) {
+ Fragment body;
+
+ const intptr_t num_arguments =
+ native_calling_convention.argument_locations().length() + 1;
+ InputsArray* arguments = new (Z) InputsArray(num_arguments);
+ arguments->FillWith(nullptr, 0, num_arguments);
+ for (intptr_t i = num_arguments - 1; i >= 0; --i) {
+ (*arguments)[i] = Pop();
+ }
+ auto* const call =
+ new (Z) CCallInstr(Z, native_calling_convention, arguments);
+
+ Push(call);
+ body <<= call;
+
+ return body;
+}
+
+Fragment FlowGraphBuilder::CCall(intptr_t num_arguments,
+ Representation representation) {
+ const auto& native_function_type =
+ *compiler::ffi::NativeFunctionType::FromUnboxedRepresentation(
+ Z, num_arguments, representation);
+ const auto& native_calling_convention =
+ compiler::ffi::NativeCallingConvention::FromSignature(
+ Z, native_function_type);
+ return CCall(native_calling_convention);
+}
+
Fragment FlowGraphBuilder::RethrowException(TokenPosition position,
int catch_try_index) {
Fragment instructions;
@@ -3982,9 +4014,20 @@
}
Fragment FlowGraphBuilder::EnterHandleScope() {
- auto* instr = new (Z) EnterHandleScopeInstr();
- Push(instr);
- return Fragment(instr);
+ Fragment body;
+ body += LoadThread();
+ body += ConvertUntaggedToUnboxed(kUnboxedIntPtr); // argument.
+
+ // LoadThread again, we can't store it in a temp because it will end up
+ // in the environment of the FfiCall as untagged then.
+ body += LoadThread();
+ body += LoadUntagged(compiler::target::Thread::OffsetFromThread(
+ &kEnterHandleScopeRuntimeEntry));
+ body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr); // function address.
+
+ body += CCall(/*num_arguments=*/1);
+
+ return body;
}
Fragment FlowGraphBuilder::GetTopHandleScope() {
@@ -3996,18 +4039,33 @@
}
Fragment FlowGraphBuilder::ExitHandleScope() {
- auto* instr = new (Z) ExitHandleScopeInstr();
- return Fragment(instr);
+ Fragment code;
+ code += LoadThread();
+ code += ConvertUntaggedToUnboxed(kUnboxedIntPtr); // argument.
+
+ code += LoadThread();
+ code += LoadUntagged(compiler::target::Thread::OffsetFromThread(
+ &kExitHandleScopeRuntimeEntry));
+ code += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr); // function address.
+
+ code += CCall(/*num_arguments=*/1);
+
+ code += Drop();
+ return code;
}
Fragment FlowGraphBuilder::AllocateHandle() {
Fragment code;
// Get a reference to the top handle scope.
code += GetTopHandleScope();
- Value* api_local_scope_value = Pop();
- auto* instr = new (Z) AllocateHandleInstr(api_local_scope_value);
- Push(instr);
- code <<= instr;
+
+ code += LoadThread();
+ code += LoadUntagged(
+ compiler::target::Thread::OffsetFromThread(&kAllocateHandleRuntimeEntry));
+ code += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr); // function address.
+
+ code += CCall(/*num_arguments=*/1);
+
return code;
}
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 697be82..ff641cc 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -196,6 +196,11 @@
Fragment FfiCall(const compiler::ffi::CallMarshaller& marshaller);
+ Fragment CCall(
+ const compiler::ffi::NativeCallingConvention& native_calling_convention);
+ Fragment CCall(intptr_t num_arguments,
+ Representation representation = kUnboxedFfiIntPtr);
+
Fragment RethrowException(TokenPosition position, int catch_try_index);
Fragment LoadLocal(LocalVariable* variable);
Fragment IndirectGoto(intptr_t target_count);
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index ac9d41a..a3fcc07 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -3722,7 +3722,6 @@
return GetThreadForNativeCallback(callback_id, 0);
}
-// This is called directly by EnterHandleScopeInstr.
extern "C" ApiLocalScope* DLRT_EnterHandleScope(Thread* thread) {
CHECK_STACK_ALIGNMENT;
TRACE_RUNTIME_CALL("EnterHandleScope %p", thread);
@@ -3737,7 +3736,6 @@
false /* is_float */,
reinterpret_cast<RuntimeFunction>(&DLRT_EnterHandleScope));
-// This is called directly by ExitHandleScopeInstr.
extern "C" void DLRT_ExitHandleScope(Thread* thread) {
CHECK_STACK_ALIGNMENT;
TRACE_RUNTIME_CALL("ExitHandleScope %p", thread);
@@ -3750,7 +3748,6 @@
false /* is_float */,
reinterpret_cast<RuntimeFunction>(&DLRT_ExitHandleScope));
-// This is called directly by AllocateHandleInstr.
extern "C" LocalHandle* DLRT_AllocateHandle(ApiLocalScope* scope) {
CHECK_STACK_ALIGNMENT;
TRACE_RUNTIME_CALL("AllocateHandle %p", scope);
diff --git a/tools/VERSION b/tools/VERSION
index d5db85d..df385d9 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 152
+PRERELEASE 153
PRERELEASE_PATCH 0
\ No newline at end of file