Version 2.14.0-267.0.dev
Merge commit 'f5326473c2db3f55996a645d5e7e59743766fe10' into 'dev'
diff --git a/runtime/tests/concurrency/stress_test_list.json b/runtime/tests/concurrency/stress_test_list.json
index f600f8b..68a2c00 100644
--- a/runtime/tests/concurrency/stress_test_list.json
+++ b/runtime/tests/concurrency/stress_test_list.json
@@ -402,7 +402,6 @@
"../../../tests/corelib/regexp/repeat-match-waldemar_test.dart",
"../../../tests/corelib/regexp/results-cache_test.dart",
"../../../tests/corelib/regexp/stack-overflow2_test.dart",
- "../../../tests/corelib/regexp/stack-overflow_test.dart",
"../../../tests/corelib/regexp/standalones_test.dart",
"../../../tests/corelib/regexp/toString_test.dart",
"../../../tests/corelib/regexp/unicode-character-ranges_test.dart",
@@ -3306,7 +3305,6 @@
"../../../tests/standalone/io/http_request_pipeling_test.dart",
"../../../tests/standalone/io/http_requested_uri_test.dart",
"../../../tests/standalone/io/http_response_deadline_test.dart",
- "../../../tests/standalone/io/http_reuse_server_port_test.dart",
"../../../tests/standalone/io/http_session_test.dart",
"../../../tests/standalone/io/http_shutdown_test.dart",
"../../../tests/standalone/io/http_stream_close_test.dart",
@@ -3823,7 +3821,6 @@
"../../../tests/corelib_2/regexp/repeat-match-waldemar_test.dart",
"../../../tests/corelib_2/regexp/results-cache_test.dart",
"../../../tests/corelib_2/regexp/stack-overflow2_test.dart",
- "../../../tests/corelib_2/regexp/stack-overflow_test.dart",
"../../../tests/corelib_2/regexp/standalones_test.dart",
"../../../tests/corelib_2/regexp/toString_test.dart",
"../../../tests/corelib_2/regexp/unicode-character-ranges_test.dart",
@@ -6643,7 +6640,6 @@
"../../../tests/standalone_2/io/http_request_pipeling_test.dart",
"../../../tests/standalone_2/io/http_requested_uri_test.dart",
"../../../tests/standalone_2/io/http_response_deadline_test.dart",
- "../../../tests/standalone_2/io/http_reuse_server_port_test.dart",
"../../../tests/standalone_2/io/http_session_test.dart",
"../../../tests/standalone_2/io/http_shutdown_test.dart",
"../../../tests/standalone_2/io/http_stream_close_test.dart",
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index da234e4..60fdf3a 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -791,10 +791,6 @@
}
}
-void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) {
- SetValue(instr, non_constant_);
-}
-
void ConstantPropagator::VisitUtf8Scan(Utf8ScanInstr* instr) {
SetValue(instr, non_constant_);
}
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 49131ee..b121598 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -5243,8 +5243,92 @@
return false;
}
+static const String& EvaluateToString(Zone* zone, Definition* defn) {
+ if (auto konst = defn->AsConstant()) {
+ const Object& obj = konst->value();
+ if (obj.IsString()) {
+ return String::Cast(obj);
+ } else if (obj.IsSmi()) {
+ const char* cstr = obj.ToCString();
+ return String::Handle(zone, String::New(cstr, Heap::kOld));
+ } else if (obj.IsBool()) {
+ return Bool::Cast(obj).value() ? Symbols::True() : Symbols::False();
+ } else if (obj.IsNull()) {
+ return Symbols::null();
+ }
+ }
+ return String::null_string();
+}
+
+static Definition* CanonicalizeStringInterpolate(StaticCallInstr* call,
+ FlowGraph* flow_graph) {
+ auto arg0 = call->ArgumentValueAt(0)->definition();
+ auto create_array = arg0->AsCreateArray();
+ if (create_array == nullptr) {
+ // Do not try to fold interpolate if array is an OSR argument.
+ ASSERT(flow_graph->IsCompiledForOsr());
+ ASSERT(arg0->IsPhi() || arg0->IsParameter());
+ return call;
+ }
+ // Check if the string interpolation has only constant inputs.
+ Value* num_elements = create_array->num_elements();
+ if (!num_elements->BindsToConstant() ||
+ !num_elements->BoundConstant().IsSmi()) {
+ return call;
+ }
+ const intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value();
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ GrowableHandlePtrArray<const String> pieces(zone, length);
+ for (intptr_t i = 0; i < length; i++) {
+ pieces.Add(Object::null_string());
+ }
+
+ for (Value::Iterator it(create_array->input_use_list()); !it.Done();
+ it.Advance()) {
+ auto store = it.Current()->instruction()->AsStoreIndexed();
+ if (store == nullptr || !store->index()->BindsToConstant() ||
+ !store->index()->BoundConstant().IsSmi()) {
+ return call;
+ }
+ intptr_t store_index = Smi::Cast(store->index()->BoundConstant()).Value();
+ ASSERT(store_index < length);
+ const String& piece =
+ EvaluateToString(flow_graph->zone(), store->value()->definition());
+ if (!piece.IsNull()) {
+ pieces.SetAt(store_index, piece);
+ } else {
+ return call;
+ }
+ }
+
+ const String& concatenated =
+ String::ZoneHandle(zone, Symbols::FromConcatAll(thread, pieces));
+ return flow_graph->GetConstant(concatenated);
+}
+
+static Definition* CanonicalizeStringInterpolateSingle(StaticCallInstr* call,
+ FlowGraph* flow_graph) {
+ auto arg0 = call->ArgumentValueAt(0)->definition();
+ const auto& result = EvaluateToString(flow_graph->zone(), arg0);
+ if (!result.IsNull()) {
+ return flow_graph->GetConstant(String::ZoneHandle(
+ flow_graph->zone(), Symbols::New(flow_graph->thread(), result)));
+ }
+ return call;
+}
+
Definition* StaticCallInstr::Canonicalize(FlowGraph* flow_graph) {
- if (!CompilerState::Current().is_aot()) {
+ auto& compiler_state = CompilerState::Current();
+
+ if (function().ptr() == compiler_state.StringBaseInterpolate().ptr()) {
+ return CanonicalizeStringInterpolate(this, flow_graph);
+ } else if (function().ptr() ==
+ compiler_state.StringBaseInterpolateSingle().ptr()) {
+ return CanonicalizeStringInterpolateSingle(this, flow_graph);
+ }
+
+ if (!compiler_state.is_aot()) {
return this;
}
@@ -5964,101 +6048,6 @@
}
}
-const Function& StringInterpolateInstr::CallFunction() const {
- if (function_.IsNull()) {
- const int kTypeArgsLen = 0;
- const int kNumberOfArguments = 1;
- const Array& kNoArgumentNames = Object::null_array();
- const Class& cls =
- Class::Handle(Library::LookupCoreClass(Symbols::StringBase()));
- ASSERT(!cls.IsNull());
- function_ = Resolver::ResolveStatic(
- cls, Library::PrivateCoreLibName(Symbols::Interpolate()), kTypeArgsLen,
- kNumberOfArguments, kNoArgumentNames);
- }
- ASSERT(!function_.IsNull());
- return function_;
-}
-
-// Replace StringInterpolateInstr with a constant string if all inputs are
-// constant of [string, number, boolean, null].
-// Leave the CreateArrayInstr and StoreIndexedInstr in the stream in case
-// deoptimization occurs.
-Definition* StringInterpolateInstr::Canonicalize(FlowGraph* flow_graph) {
- // The following graph structure is generated by the graph builder:
- // v2 <- CreateArray(v0)
- // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value.
- // ..
- // v8 <- StringInterpolate(v2)
-
- // Don't compile-time fold when optimizing the interpolation function itself.
- if (flow_graph->function().ptr() == CallFunction().ptr()) {
- return this;
- }
-
- CreateArrayInstr* create_array = value()->definition()->AsCreateArray();
- if (create_array == nullptr) {
- // Do not try to fold interpolate if array is an OSR argument.
- ASSERT(flow_graph->IsCompiledForOsr());
- ASSERT(value()->definition()->IsPhi() ||
- value()->definition()->IsParameter());
- return this;
- }
- // Check if the string interpolation has only constant inputs.
- Value* num_elements = create_array->num_elements();
- if (!num_elements->BindsToConstant() ||
- !num_elements->BoundConstant().IsSmi()) {
- return this;
- }
- const intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value();
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- GrowableHandlePtrArray<const String> pieces(zone, length);
- for (intptr_t i = 0; i < length; i++) {
- pieces.Add(Object::null_string());
- }
-
- for (Value::Iterator it(create_array->input_use_list()); !it.Done();
- it.Advance()) {
- Instruction* curr = it.Current()->instruction();
- if (curr == this) continue;
-
- StoreIndexedInstr* store = curr->AsStoreIndexed();
- if (store == nullptr || !store->index()->BindsToConstant() ||
- !store->index()->BoundConstant().IsSmi()) {
- return this;
- }
- intptr_t store_index = Smi::Cast(store->index()->BoundConstant()).Value();
- ASSERT(store_index < length);
- ASSERT(store != NULL);
- if (store->value()->definition()->IsConstant()) {
- ASSERT(store->index()->BindsToConstant());
- const Object& obj = store->value()->definition()->AsConstant()->value();
- // TODO(srdjan): Verify if any other types should be converted as well.
- if (obj.IsString()) {
- pieces.SetAt(store_index, String::Cast(obj));
- } else if (obj.IsSmi()) {
- const char* cstr = obj.ToCString();
- pieces.SetAt(store_index,
- String::Handle(zone, String::New(cstr, Heap::kOld)));
- } else if (obj.IsBool()) {
- pieces.SetAt(store_index, Bool::Cast(obj).value() ? Symbols::True()
- : Symbols::False());
- } else if (obj.IsNull()) {
- pieces.SetAt(store_index, Symbols::null());
- } else {
- return this;
- }
- } else {
- return this;
- }
- }
-
- const String& concatenated =
- String::ZoneHandle(zone, Symbols::FromConcatAll(thread, pieces));
- return flow_graph->GetConstant(concatenated);
-}
-
static AlignmentType StrengthenAlignment(intptr_t cid,
AlignmentType alignment) {
switch (cid) {
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 5f22ad8..1744e17 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -478,7 +478,6 @@
M(Constraint, kNoGC) \
M(StringToCharCode, kNoGC) \
M(OneByteStringFromCharCode, kNoGC) \
- M(StringInterpolate, _) \
M(Utf8Scan, kNoGC) \
M(InvokeMathCFunction, kNoGC) \
M(TruncDivMod, kNoGC) \
@@ -5850,41 +5849,6 @@
DISALLOW_COPY_AND_ASSIGN(StringToCharCodeInstr);
};
-class StringInterpolateInstr : public TemplateDefinition<1, Throws> {
- public:
- StringInterpolateInstr(Value* value,
- const InstructionSource& source,
- intptr_t deopt_id)
- : TemplateDefinition(source, deopt_id),
- token_pos_(source.token_pos),
- function_(Function::ZoneHandle()) {
- SetInputAt(0, value);
- }
-
- Value* value() const { return inputs_[0]; }
- virtual TokenPosition token_pos() const { return token_pos_; }
-
- virtual CompileType ComputeType() const;
- // Issues a static call to Dart code which calls toString on objects.
- virtual bool HasUnknownSideEffects() const { return true; }
- virtual bool CanCallDart() const { return true; }
- virtual bool ComputeCanDeoptimize() const {
- return !CompilerState::Current().is_aot();
- }
-
- const Function& CallFunction() const;
-
- virtual Definition* Canonicalize(FlowGraph* flow_graph);
-
- DECLARE_INSTRUCTION(StringInterpolate)
-
- private:
- const TokenPosition token_pos_;
- Function& function_;
-
- DISALLOW_COPY_AND_ASSIGN(StringInterpolateInstr);
-};
-
// Scanning instruction to compute the result size and decoding parameters
// for the UTF-8 decoder. Equivalent to:
//
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 6b44b0d..0ac5dfd 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1727,31 +1727,6 @@
__ SmiTag(result);
}
-LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps = 0;
- LocationSummary* summary = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
- summary->set_in(0, Location::RegisterLocation(R0));
- summary->set_out(0, Location::RegisterLocation(R0));
- return summary;
-}
-
-void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- const Register array = locs()->in(0).reg();
- __ Push(array);
- const int kTypeArgsLen = 0;
- const int kNumberOfArguments = 1;
- constexpr int kSizeOfArguments = 1;
- const Array& kNoArgumentNames = Object::null_array();
- ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
- kNoArgumentNames);
- compiler->GenerateStaticCall(deopt_id(), source(), CallFunction(), args_info,
- locs(), ICData::Handle(), ICData::kStatic);
- ASSERT(locs()->out(0).reg() == R0);
-}
-
LocationSummary* Utf8ScanInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 5;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 0f09726..d67e9e9 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -1575,31 +1575,6 @@
__ SmiTag(result);
}
-LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps = 0;
- LocationSummary* summary = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
- summary->set_in(0, Location::RegisterLocation(R0));
- summary->set_out(0, Location::RegisterLocation(R0));
- return summary;
-}
-
-void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- const Register array = locs()->in(0).reg();
- __ Push(array);
- const int kTypeArgsLen = 0;
- const int kNumberOfArguments = 1;
- constexpr int kSizeOfArguments = 1;
- const Array& kNoArgumentNames = Object::null_array();
- ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
- kNoArgumentNames);
- compiler->GenerateStaticCall(deopt_id(), source(), CallFunction(), args_info,
- locs(), ICData::Handle(), ICData::kStatic);
- ASSERT(locs()->out(0).reg() == R0);
-}
-
LocationSummary* Utf8ScanInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 5;
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index d16dab4..f7ef9ae 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -1272,31 +1272,6 @@
__ Bind(&done);
}
-LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps = 0;
- LocationSummary* summary = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
- summary->set_in(0, Location::RegisterLocation(EAX));
- summary->set_out(0, Location::RegisterLocation(EAX));
- return summary;
-}
-
-void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Register array = locs()->in(0).reg();
- __ pushl(array);
- const int kTypeArgsLen = 0;
- const int kNumberOfArguments = 1;
- constexpr int kSizeOfArguments = 1;
- const Array& kNoArgumentNames = Object::null_array();
- ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
- kNoArgumentNames);
- compiler->GenerateStaticCall(deopt_id(), source(), CallFunction(), args_info,
- locs(), ICData::Handle(), ICData::kStatic);
- ASSERT(locs()->out(0).reg() == EAX);
-}
-
LocationSummary* Utf8ScanInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 5;
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 56144e61..7882a76 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1488,31 +1488,6 @@
__ Bind(&done);
}
-LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps = 0;
- LocationSummary* summary = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
- summary->set_in(0, Location::RegisterLocation(RAX));
- summary->set_out(0, Location::RegisterLocation(RAX));
- return summary;
-}
-
-void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Register array = locs()->in(0).reg();
- __ pushq(array);
- const int kTypeArgsLen = 0;
- const int kNumberOfArguments = 1;
- constexpr int kSizeOfArguments = 1;
- const Array& kNoArgumentNames = Object::null_array();
- ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
- kNoArgumentNames);
- compiler->GenerateStaticCall(deopt_id(), source(), CallFunction(), args_info,
- locs(), ICData::Handle(), ICData::kStatic);
- ASSERT(locs()->out(0).reg() == RAX);
-}
-
LocationSummary* Utf8ScanInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 5;
diff --git a/runtime/vm/compiler/backend/redundancy_elimination_test.cc b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
index 2e88fcc..2668f1d 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination_test.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
@@ -1189,13 +1189,14 @@
49: ParallelMove rdx <- rcx, rax <- rax
50: StoreIndexed(v24, v53, v580)
51: ParallelMove rax <- rcx
- 52: v54 <- StringInterpolate:44(v24) T{String}
+ PushArgument(v24)
+ 52: v54 <- StaticCall:44(_StringBase._interpolate, v24) T{String}
53: ParallelMove rax <- rax
54: Return:48(v54)
*/
CreateArrayInstr* create_array = nullptr;
- StringInterpolateInstr* string_interpolate = nullptr;
+ StaticCallInstr* string_interpolate = nullptr;
ILMatcher cursor(flow_graph, entry, /*trace=*/true,
ParallelMovesHandling::kSkip);
@@ -1225,11 +1226,12 @@
kMatchAndMoveStoreIndexed,
kMatchAndMoveBox,
kMatchAndMoveStoreIndexed,
- {kMatchAndMoveStringInterpolate, &string_interpolate},
+ kMatchAndMovePushArgument,
+ {kMatchAndMoveStaticCall, &string_interpolate},
kMatchReturn,
}));
- EXPECT(string_interpolate->value()->definition() == create_array);
+ EXPECT(string_interpolate->ArgumentAt(0) == create_array);
}
#if !defined(TARGET_ARCH_IA32)
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index c28b9c7..9aecb2c 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1503,11 +1503,6 @@
return CompileType::FromCid(kSmiCid);
}
-CompileType StringInterpolateInstr::ComputeType() const {
- // TODO(srdjan): Do better and determine if it is a one or two byte string.
- return CompileType::String();
-}
-
CompileType LoadStaticFieldInstr::ComputeType() const {
const Field& field = this->field();
bool is_nullable = CompileType::kCanBeNull;
diff --git a/runtime/vm/compiler/compiler_state.cc b/runtime/vm/compiler/compiler_state.cc
index 38d4932..b886b6f 100644
--- a/runtime/vm/compiler/compiler_state.cc
+++ b/runtime/vm/compiler/compiler_state.cc
@@ -98,4 +98,34 @@
return *comparable_class_;
}
+const Function& CompilerState::StringBaseInterpolateSingle() {
+ if (interpolate_single_ == nullptr) {
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+
+ const Class& cls =
+ Class::Handle(Library::LookupCoreClass(Symbols::StringBase()));
+ ASSERT(!cls.IsNull());
+ interpolate_single_ = &Function::ZoneHandle(
+ zone, cls.LookupFunctionAllowPrivate(Symbols::InterpolateSingle()));
+ ASSERT(!interpolate_single_->IsNull());
+ }
+ return *interpolate_single_;
+}
+
+const Function& CompilerState::StringBaseInterpolate() {
+ if (interpolate_ == nullptr) {
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+
+ const Class& cls =
+ Class::Handle(Library::LookupCoreClass(Symbols::StringBase()));
+ ASSERT(!cls.IsNull());
+ interpolate_ = &Function::ZoneHandle(
+ zone, cls.LookupFunctionAllowPrivate(Symbols::Interpolate()));
+ ASSERT(!interpolate_->IsNull());
+ }
+ return *interpolate_;
+}
+
} // namespace dart
diff --git a/runtime/vm/compiler/compiler_state.h b/runtime/vm/compiler/compiler_state.h
index db608f3..1520b40 100644
--- a/runtime/vm/compiler/compiler_state.h
+++ b/runtime/vm/compiler/compiler_state.h
@@ -99,6 +99,12 @@
// Returns class Comparable<T> from dart:core.
const Class& ComparableClass();
+ // Returns _StringBase._interpolate
+ const Function& StringBaseInterpolate();
+
+ // Returns _StringBase._interpolateSingle
+ const Function& StringBaseInterpolateSingle();
+
private:
CHA cha_;
intptr_t deopt_id_ = 0;
@@ -118,6 +124,8 @@
// Lookup cache for various classes (to avoid polluting object store with
// compiler specific classes).
const Class* comparable_class_ = nullptr;
+ const Function* interpolate_ = nullptr;
+ const Function* interpolate_single_ = nullptr;
CompilerState* previous_;
};
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index f750101..4c3a5cf 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -1149,14 +1149,6 @@
return Fragment(call);
}
-Fragment BaseFlowGraphBuilder::StringInterpolate(TokenPosition position) {
- Value* array = Pop();
- StringInterpolateInstr* interpolate = new (Z) StringInterpolateInstr(
- array, InstructionSource(position), GetNextDeoptId());
- Push(interpolate);
- return Fragment(interpolate);
-}
-
void BaseFlowGraphBuilder::reset_context_depth_for_deopt_id(intptr_t deopt_id) {
if (is_recording_context_levels()) {
for (intptr_t i = 0, n = context_level_array_->length(); i < n; i += 2) {
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index 6873a4f..edad1e4 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -411,10 +411,6 @@
intptr_t argument_count,
const Array& argument_names);
- // Builds StringInterpolate instruction, an equivalent of
- // _StringBase._interpolate call.
- Fragment StringInterpolate(TokenPosition position);
-
// Pops function type arguments, instantiator type arguments, dst_type, and
// value; and type checks value against the type arguments.
Fragment AssertAssignable(
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
index 1bd0f27..f280b55 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
@@ -88,7 +88,7 @@
kMatchAndMoveCreateArray,
{kMatchAndMoveStoreIndexed, &store1},
{kMatchAndMoveStoreIndexed, &store2},
- kMatchAndMoveStringInterpolate,
+ kMatchAndMoveStaticCall,
kMoveDebugStepChecks,
kMatchReturn,
}));
@@ -147,7 +147,7 @@
{kMatchAndMoveStoreIndexed, &store1},
{kMatchAndMoveStoreIndexed, &store2},
{kMatchAndMoveStoreIndexed, &store3},
- kMatchAndMoveStringInterpolate,
+ kMatchAndMoveStaticCall,
kMoveDebugStepChecks,
kMatchReturn,
}));
@@ -215,7 +215,7 @@
{kMatchAndMoveStoreIndexed, &store1},
{kMatchAndMoveStoreIndexed, &store2},
{kMatchAndMoveStoreIndexed, &store3},
- kMatchAndMoveStringInterpolate,
+ kMatchAndMoveStaticCall,
kMoveDebugStepChecks,
kMatchReturn,
}));
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 8c9be51..c4a43ff 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -617,19 +617,18 @@
}
Fragment FlowGraphBuilder::StringInterpolateSingle(TokenPosition position) {
- const int kTypeArgsLen = 0;
- const int kNumberOfArguments = 1;
- const Array& kNoArgumentNames = Object::null_array();
- const Class& cls =
- Class::Handle(Library::LookupCoreClass(Symbols::StringBase()));
- ASSERT(!cls.IsNull());
- const Function& function = Function::ZoneHandle(
- Z, Resolver::ResolveStatic(
- cls, Library::PrivateCoreLibName(Symbols::InterpolateSingle()),
- kTypeArgsLen, kNumberOfArguments, kNoArgumentNames));
+ Fragment instructions;
+ instructions += StaticCall(
+ position, CompilerState::Current().StringBaseInterpolateSingle(),
+ /* argument_count = */ 1, ICData::kStatic);
+ return instructions;
+}
+
+Fragment FlowGraphBuilder::StringInterpolate(TokenPosition position) {
Fragment instructions;
instructions +=
- StaticCall(position, function, /* argument_count = */ 1, ICData::kStatic);
+ StaticCall(position, CompilerState::Current().StringBaseInterpolate(),
+ /* argument_count = */ 1, ICData::kStatic);
return instructions;
}
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 7f606e4..f9d1a6e 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -222,6 +222,7 @@
intptr_t type_args_len = 0,
bool use_unchecked_entry = false);
Fragment StringInterpolateSingle(TokenPosition position);
+ Fragment StringInterpolate(TokenPosition position);
Fragment ThrowTypeError();
Fragment ThrowNoSuchMethodError(const Function& target);
Fragment ThrowLateInitializationError(TokenPosition position,
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 3f46559..3810986 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -81,7 +81,7 @@
V(::, _toClampedUint8, ConvertIntToClampedUint8, 0x00fc4650) \
V(::, copyRangeFromUint8ListToOneByteString, \
CopyRangeFromUint8ListToOneByteString, 0x0df019c5) \
- V(_StringBase, _interpolate, StringBaseInterpolate, 0xea1eac09) \
+ V(_StringBase, _interpolate, StringBaseInterpolate, 0xea1eafca) \
V(_IntegerImplementation, toDouble, IntegerToDouble, 0x97728b46) \
V(_Double, _add, DoubleAdd, 0xea666327) \
V(_Double, _sub, DoubleSub, 0x28474c2e) \
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 0ee8b47..a645736 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -4520,8 +4520,8 @@
"Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_OneByteString\",\"_"
"vmName\":\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
"\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
- "patch\\/string_patch.dart\",\"_kind\":\"kernel\"},\"tokenPos\":32310,"
- "\"endTokenPos\":44599},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+ "patch\\/string_patch.dart\",\"_kind\":\"kernel\"},\"tokenPos\":32339,"
+ "\"endTokenPos\":44628},\"library\":{\"type\":\"@Library\",\"fixedId\":"
"true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
"\"identityHashCode\":0,\"kind\":\"String\",\"id\":\"\",\"length\":2,"
"\"valueAsString\":\"dw\"}",
diff --git a/sdk/lib/_internal/vm/lib/string_patch.dart b/sdk/lib/_internal/vm/lib/string_patch.dart
index be6b858..b02d273 100644
--- a/sdk/lib/_internal/vm/lib/string_patch.dart
+++ b/sdk/lib/_internal/vm/lib/string_patch.dart
@@ -846,6 +846,7 @@
*/
@pragma("vm:recognized", "other")
@pragma("vm:entry-point", "call")
+ @pragma("vm:never-inline")
static String _interpolate(final List values) {
final numValues = values.length;
int totalLength = 0;
diff --git a/tools/VERSION b/tools/VERSION
index 1390739..1e2134a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 266
+PRERELEASE 267
PRERELEASE_PATCH 0
\ No newline at end of file