Introduce inline cache reload rule attribute to static call AST node and ICData.

Reload rule describes how inline cache has to be processed during hot reload, whether it should
be updated, reset or preserved.

Bug: dartbug.com/30639
Change-Id: I40b63ade786456ec48d4fa205a076654c2996bce
Reviewed-on: https://dart-review.googlesource.com/7586
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Alexander Aprelev
2017-09-25 20:18:58 +00:00
committed by commit-bot@chromium.org
parent 5263d17f74
commit 68a727fa5c
28 changed files with 378 additions and 251 deletions
+13 -2
View File
@@ -1637,10 +1637,17 @@ class StaticSetterNode : public AstNode {
class StaticCallNode : public AstNode {
public:
// The rule below is mapped to ICData::RebindRule (runtime/vm/object.h).
enum RebindRule { kNSMDispatch, kStatic, kSuper };
StaticCallNode(TokenPosition token_pos,
const Function& function,
ArgumentListNode* arguments)
: AstNode(token_pos), function_(function), arguments_(arguments) {
ArgumentListNode* arguments,
RebindRule rebind_rule)
: AstNode(token_pos),
function_(function),
arguments_(arguments),
rebind_rule_(rebind_rule) {
ASSERT(function_.IsZoneHandle());
ASSERT(arguments_ != NULL);
}
@@ -1648,6 +1655,9 @@ class StaticCallNode : public AstNode {
const Function& function() const { return function_; }
ArgumentListNode* arguments() const { return arguments_; }
RebindRule rebind_rule() const { return rebind_rule_; }
void set_rebind_rule(RebindRule rule) { rebind_rule_ = rule; }
virtual void VisitChildren(AstNodeVisitor* visitor) const {
arguments()->Visit(visitor);
}
@@ -1659,6 +1669,7 @@ class StaticCallNode : public AstNode {
private:
const Function& function_;
ArgumentListNode* arguments_;
RebindRule rebind_rule_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCallNode);
};
+5 -4
View File
@@ -178,8 +178,9 @@ void AwaitTransformer::VisitAwaitNode(AwaitNode* node) {
async_await_helper_args->Add(
new (Z) LoadLocalNode(token_pos, async_catch_error_callback));
async_await_helper_args->Add(new (Z) LoadLocalNode(token_pos, async_op));
StaticCallNode* await_helper_call = new (Z) StaticCallNode(
node->token_pos(), async_await_helper, async_await_helper_args);
StaticCallNode* await_helper_call =
new (Z) StaticCallNode(node->token_pos(), async_await_helper,
async_await_helper_args, StaticCallNode::kStatic);
preamble_->Add(
new (Z) StoreLocalNode(token_pos, result_param, await_helper_call));
@@ -362,8 +363,8 @@ void AwaitTransformer::VisitInstanceCallNode(InstanceCallNode* node) {
void AwaitTransformer::VisitStaticCallNode(StaticCallNode* node) {
ArgumentListNode* new_args =
Transform(node->arguments())->AsArgumentListNode();
result_ = MakeName(
new (Z) StaticCallNode(node->token_pos(), node->function(), new_args));
result_ = MakeName(new (Z) StaticCallNode(node->token_pos(), node->function(),
new_args, node->rebind_rule()));
}
void AwaitTransformer::VisitConstructorCallNode(ConstructorCallNode* node) {
+2 -2
View File
@@ -37,8 +37,8 @@ ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
const intptr_t kNumArgs = 1;
const Array& args_descriptor = Array::Handle(
ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs, Object::null_array()));
const ICData& ic_data = ICData::ZoneHandle(
ICData::New(function, target_name, args_descriptor, 15, 1, false));
const ICData& ic_data = ICData::ZoneHandle(ICData::New(
function, target_name, args_descriptor, 15, 1, ICData::kInstance));
// Code accessing pp is generated, but not executed. Uninitialized pp is OK.
__ set_constant_pool_allowed(true);
+14 -14
View File
@@ -206,10 +206,10 @@ bool AotCallSpecializer::TryReplaceWithHaveSameRuntimeType(
args->Add(arg);
const intptr_t kTypeArgsLen = 0;
ASSERT(call->type_args_len() == kTypeArgsLen);
StaticCallInstr* static_call = new (Z)
StaticCallInstr(call->token_pos(), have_same_runtime_type, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount());
StaticCallInstr* static_call = new (Z) StaticCallInstr(
call->token_pos(), have_same_runtime_type, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount(), ICData::kOptimized);
static_call->set_result_cid(kBoolCid);
ReplaceCall(call, static_call);
return true;
@@ -678,7 +678,7 @@ void AotCallSpecializer::VisitInstanceCall(InstanceCallInstr* instr) {
// the computed single_target.
ic_data = ICData::New(function, instr->function_name(),
args_desc_array, Thread::kNoDeoptId,
/* args_tested = */ 1, false);
/* args_tested = */ 1, ICData::kOptimized);
for (intptr_t j = 0; j < i; j++) {
ic_data.AddReceiverCheck(class_ids[j], single_target);
}
@@ -699,7 +699,7 @@ void AotCallSpecializer::VisitInstanceCall(InstanceCallInstr* instr) {
const ICData& ic_data = ICData::Handle(
ICData::New(flow_graph()->function(), instr->function_name(),
args_desc_array, Thread::kNoDeoptId,
/* args_tested = */ 1, false));
/* args_tested = */ 1, ICData::kOptimized));
cls = single_target.Owner();
ic_data.AddReceiverCheck(cls.id(), single_target);
instr->set_ic_data(&ic_data);
@@ -819,10 +819,10 @@ bool AotCallSpecializer::TryReplaceInstanceOfWithRangeCheck(
ASSERT(target.IsRecognized() && target.always_inline());
const intptr_t kTypeArgsLen = 0;
StaticCallInstr* new_call =
new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount());
StaticCallInstr* new_call = new (Z) StaticCallInstr(
call->token_pos(), target, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount(), ICData::kOptimized);
Environment* copy =
call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount());
for (intptr_t i = 0; i < args->length(); ++i) {
@@ -896,10 +896,10 @@ bool AotCallSpecializer::TryReplaceTypeCastWithRangeCheck(
ASSERT(target.always_inline());
const intptr_t kTypeArgsLen = 0;
StaticCallInstr* new_call =
new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount());
StaticCallInstr* new_call = new (Z) StaticCallInstr(
call->token_pos(), target, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount(), ICData::kOptimized);
Environment* copy =
call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount());
for (intptr_t i = 0; i < args->length(); ++i) {
+5 -4
View File
@@ -2623,9 +2623,10 @@ void Precompiler::PopulateWithICData(const Function& function,
const Array& arguments_descriptor =
Array::Handle(zone, call->GetArgumentsDescriptor());
const ICData& ic_data = ICData::ZoneHandle(
zone, ICData::New(function, call->function_name(),
arguments_descriptor, call->deopt_id(),
call->checked_argument_count(), false));
zone,
ICData::New(function, call->function_name(), arguments_descriptor,
call->deopt_id(), call->checked_argument_count(),
ICData::kInstance));
call->set_ic_data(&ic_data);
}
} else if (instr->IsStaticCall()) {
@@ -2649,7 +2650,7 @@ void Precompiler::PopulateWithICData(const Function& function,
const ICData& ic_data = ICData::ZoneHandle(
zone, ICData::New(function, String::Handle(zone, target.name()),
arguments_descriptor, call->deopt_id(),
num_args_checked, true));
num_args_checked, ICData::kStatic));
ic_data.AddTarget(target);
call->set_ic_data(&ic_data);
}
@@ -1117,7 +1117,8 @@ void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id,
const Function& function,
ArgumentsInfo args_info,
LocationSummary* locs,
const ICData& ic_data_in) {
const ICData& ic_data_in,
ICData::RebindRule rebind_rule) {
const ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original());
const Array& arguments_descriptor = Array::ZoneHandle(
zone(), ic_data.IsNull() ? args_info.ToArgumentsDescriptor()
@@ -1134,7 +1135,7 @@ void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id,
const intptr_t kNumArgsChecked = 0;
call_ic_data =
GetOrAddStaticCallICData(deopt_id, function, arguments_descriptor,
kNumArgsChecked)
kNumArgsChecked, rebind_rule)
->raw();
}
AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id, token_pos);
@@ -1551,10 +1552,10 @@ const ICData* FlowGraphCompiler::GetOrAddInstanceCallICData(
ASSERT(!res->is_static_call());
return res;
}
const ICData& ic_data =
ICData::ZoneHandle(zone(), ICData::New(parsed_function().function(),
target_name, arguments_descriptor,
deopt_id, num_args_tested, false));
const ICData& ic_data = ICData::ZoneHandle(
zone(), ICData::New(parsed_function().function(), target_name,
arguments_descriptor, deopt_id, num_args_tested,
ICData::kInstance));
#if defined(TAG_IC_DATA)
ic_data.set_tag(Instruction::kInstanceCall);
#endif
@@ -1569,7 +1570,8 @@ const ICData* FlowGraphCompiler::GetOrAddStaticCallICData(
intptr_t deopt_id,
const Function& target,
const Array& arguments_descriptor,
intptr_t num_args_tested) {
intptr_t num_args_tested,
ICData::RebindRule rebind_rule) {
if ((deopt_id_to_ic_data_ != NULL) &&
((*deopt_id_to_ic_data_)[deopt_id] != NULL)) {
const ICData* res = (*deopt_id_to_ic_data_)[deopt_id];
@@ -1581,11 +1583,12 @@ const ICData* FlowGraphCompiler::GetOrAddStaticCallICData(
ASSERT(res->is_static_call());
return res;
}
const ICData& ic_data = ICData::ZoneHandle(
zone(),
ICData::New(parsed_function().function(),
String::Handle(zone(), target.name()), arguments_descriptor,
deopt_id, num_args_tested, true));
deopt_id, num_args_tested, rebind_rule));
ic_data.AddTarget(target);
#if defined(TAG_IC_DATA)
ic_data.set_tag(Instruction::kStaticCall);
@@ -385,7 +385,8 @@ class FlowGraphCompiler : public ValueObject {
const Function& function,
ArgumentsInfo args_info,
LocationSummary* locs,
const ICData& ic_data);
const ICData& ic_data_in,
ICData::RebindRule rebind_rule);
void GenerateNumberTypeCheck(Register kClassIdReg,
const AbstractType& type,
@@ -570,7 +571,8 @@ class FlowGraphCompiler : public ValueObject {
const ICData* GetOrAddStaticCallICData(intptr_t deopt_id,
const Function& target,
const Array& arguments_descriptor,
intptr_t num_args_tested);
intptr_t num_args_tested,
ICData::RebindRule rebind_rule);
static const CallTargets* ResolveCallTargetsForReceiverCid(
intptr_t cid,
+3 -2
View File
@@ -3463,7 +3463,8 @@ void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
break;
}
call_ic_data = compiler->GetOrAddStaticCallICData(
deopt_id(), function(), arguments_descriptor, num_args_checked);
deopt_id(), function(), arguments_descriptor, num_args_checked,
rebind_rule_);
} else {
call_ic_data = &ICData::ZoneHandle(ic_data()->raw());
}
@@ -3471,7 +3472,7 @@ void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
#if !defined(TARGET_ARCH_DBC)
ArgumentsInfo args_info(type_args_len(), ArgumentCount(), argument_names());
compiler->GenerateStaticCall(deopt_id(), token_pos(), function(), args_info,
locs(), *call_ic_data);
locs(), *call_ic_data, rebind_rule_);
#else
const Array& arguments_descriptor = Array::Handle(
zone, (ic_data() == NULL) ? GetArgumentsDescriptor()
+11 -5
View File
@@ -3283,7 +3283,8 @@ class StaticCallInstr : public TemplateDartCall<0> {
const Array& argument_names,
ZoneGrowableArray<PushArgumentInstr*>* arguments,
const ZoneGrowableArray<const ICData*>& ic_data_array,
intptr_t deopt_id)
intptr_t deopt_id,
ICData::RebindRule rebind_rule)
: TemplateDartCall(deopt_id,
type_args_len,
argument_names,
@@ -3292,6 +3293,7 @@ class StaticCallInstr : public TemplateDartCall<0> {
ic_data_(NULL),
call_count_(0),
function_(function),
rebind_rule_(rebind_rule),
result_cid_(kDynamicCid),
is_known_list_constructor_(false),
identity_(AliasIdentity::Unknown()) {
@@ -3306,7 +3308,8 @@ class StaticCallInstr : public TemplateDartCall<0> {
const Array& argument_names,
ZoneGrowableArray<PushArgumentInstr*>* arguments,
intptr_t deopt_id,
intptr_t call_count)
intptr_t call_count,
ICData::RebindRule rebind_rule)
: TemplateDartCall(deopt_id,
type_args_len,
argument_names,
@@ -3315,6 +3318,7 @@ class StaticCallInstr : public TemplateDartCall<0> {
ic_data_(NULL),
call_count_(call_count),
function_(function),
rebind_rule_(rebind_rule),
result_cid_(kDynamicCid),
is_known_list_constructor_(false),
identity_(AliasIdentity::Unknown()) {
@@ -3333,9 +3337,10 @@ class StaticCallInstr : public TemplateDartCall<0> {
for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
args->Add(call->PushArgumentAt(i));
}
return new (zone) StaticCallInstr(
call->token_pos(), target, call->type_args_len(),
call->argument_names(), args, call->deopt_id(), call->CallCount());
return new (zone)
StaticCallInstr(call->token_pos(), target, call->type_args_len(),
call->argument_names(), args, call->deopt_id(),
call->CallCount(), ICData::kStatic);
}
// ICData for static calls carries call count.
@@ -3383,6 +3388,7 @@ class StaticCallInstr : public TemplateDartCall<0> {
const ICData* ic_data_;
const intptr_t call_count_;
const Function& function_;
const ICData::RebindRule rebind_rule_;
intptr_t result_cid_; // For some library functions we know the result.
// 'True' for recognized list constructors.
+4 -2
View File
@@ -912,7 +912,8 @@ void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Array& kNoArgumentNames = Object::null_array();
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
args_info, locs(), ICData::Handle());
args_info, locs(), ICData::Handle(),
ICData::kStatic);
ASSERT(locs()->out(0).reg() == R0);
}
@@ -5573,7 +5574,8 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Array& kNoArgumentNames = Object::null_array();
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
args_info, locs(), ICData::Handle());
args_info, locs(), ICData::Handle(),
ICData::kStatic);
__ Bind(&done);
}
+4 -2
View File
@@ -774,7 +774,8 @@ void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Array& kNoArgumentNames = Object::null_array();
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
args_info, locs(), ICData::Handle());
args_info, locs(), ICData::Handle(),
ICData::kStatic);
ASSERT(locs()->out(0).reg() == R0);
}
@@ -4798,7 +4799,8 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Array& kNoArgumentNames = Object::null_array();
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
args_info, locs(), ICData::Handle());
args_info, locs(), ICData::Handle(),
ICData::kStatic);
__ Bind(&done);
}
+4 -2
View File
@@ -841,7 +841,8 @@ void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Array& kNoArgumentNames = Object::null_array();
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
args_info, locs(), ICData::Handle());
args_info, locs(), ICData::Handle(),
ICData::kStatic);
ASSERT(locs()->out(0).reg() == EAX);
}
@@ -5101,7 +5102,8 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Array& kNoArgumentNames = Object::null_array();
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
args_info, locs(), ICData::Handle());
args_info, locs(), ICData::Handle(),
ICData::kStatic);
__ Bind(&done);
}
+4 -2
View File
@@ -814,7 +814,8 @@ void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Array& kNoArgumentNames = Object::null_array();
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
args_info, locs(), ICData::Handle());
args_info, locs(), ICData::Handle(),
ICData::kStatic);
ASSERT(locs()->out(0).reg() == RAX);
}
@@ -5058,7 +5059,8 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Array& kNoArgumentNames = Object::null_array();
ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames);
compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
args_info, locs(), ICData::Handle());
args_info, locs(), ICData::Handle(),
ICData::kStatic);
__ Bind(&done);
}
+4 -4
View File
@@ -1449,10 +1449,10 @@ void CallSpecializer::ReplaceWithTypeCast(InstanceCallInstr* call) {
ASSERT(target.always_inline());
const intptr_t kTypeArgsLen = 0;
StaticCallInstr* new_call =
new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount());
StaticCallInstr* new_call = new (Z) StaticCallInstr(
call->token_pos(), target, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount(), ICData::kStatic);
Environment* copy =
call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount());
for (intptr_t i = 0; i < args->length(); ++i) {
+12 -9
View File
@@ -37,7 +37,8 @@ CODEGEN_TEST2_GENERATE(SimpleStaticCallCodegen, function, test) {
// Wrap the SmiReturnCodegen test above as a static function and call it.
ArgumentListNode* no_arguments = new ArgumentListNode(kPos);
test->node_sequence()->Add(
new ReturnNode(kPos, new StaticCallNode(kPos, function, no_arguments)));
new ReturnNode(kPos, new StaticCallNode(kPos, function, no_arguments,
StaticCallNode::kStatic)));
}
CODEGEN_TEST2_RUN(SimpleStaticCallCodegen, SmiReturnCodegen, Smi::New(3))
@@ -67,8 +68,9 @@ CODEGEN_TEST2_GENERATE(StaticCallReturnParameterCodegen, function, test) {
SequenceNode* node_seq = test->node_sequence();
ArgumentListNode* arguments = new ArgumentListNode(kPos);
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))));
node_seq->Add(
new ReturnNode(kPos, new StaticCallNode(kPos, function, arguments)));
node_seq->Add(new ReturnNode(
kPos,
new StaticCallNode(kPos, function, arguments, StaticCallNode::kStatic)));
}
CODEGEN_TEST2_RUN(StaticCallReturnParameterCodegen,
ReturnParameterCodegen,
@@ -102,8 +104,9 @@ CODEGEN_TEST2_GENERATE(StaticCallSmiParamSumCodegen, function, test) {
ArgumentListNode* arguments = new ArgumentListNode(kPos);
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(3))));
arguments->Add(new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2))));
node_seq->Add(
new ReturnNode(kPos, new StaticCallNode(kPos, function, arguments)));
node_seq->Add(new ReturnNode(
kPos,
new StaticCallNode(kPos, function, arguments, StaticCallNode::kStatic)));
}
CODEGEN_TEST2_RUN(StaticCallSmiParamSumCodegen, SmiParamSumCodegen, Smi::New(5))
@@ -246,10 +249,10 @@ CODEGEN_TEST_GENERATE(StaticCallCodegen, test) {
EXPECT(function_fly.HasCode());
ArgumentListNode* no_arguments = new ArgumentListNode(kPos);
StaticCallNode* call_bar =
new StaticCallNode(kPos, function_bar, no_arguments);
StaticCallNode* call_fly =
new StaticCallNode(kPos, function_fly, no_arguments);
StaticCallNode* call_bar = new StaticCallNode(
kPos, function_bar, no_arguments, StaticCallNode::kStatic);
StaticCallNode* call_fly = new StaticCallNode(
kPos, function_fly, no_arguments, StaticCallNode::kStatic);
BinaryOpNode* add_node =
new BinaryOpNode(kPos, Token::kADD, call_bar, call_fly);
@@ -1110,11 +1110,12 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
ZoneGrowableArray<PushArgumentInstr*>* no_arguments =
new (Z) ZoneGrowableArray<PushArgumentInstr*>(0);
const int kTypeArgsLen = 0;
StaticCallInstr* call_async_clear_thread_stack_trace = new (Z)
StaticCallInstr(node->token_pos().ToSynthetic(),
async_clear_thread_stack_trace, kTypeArgsLen,
Object::null_array(), no_arguments,
owner()->ic_data_array(), owner()->GetNextDeoptId());
StaticCallInstr* call_async_clear_thread_stack_trace =
new (Z) StaticCallInstr(node->token_pos().ToSynthetic(),
async_clear_thread_stack_trace, kTypeArgsLen,
Object::null_array(), no_arguments,
owner()->ic_data_array(),
owner()->GetNextDeoptId(), ICData::kStatic);
Do(call_async_clear_thread_stack_trace);
}
@@ -1150,7 +1151,7 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
StaticCallInstr* call = new (Z) StaticCallInstr(
node->token_pos().ToSynthetic(), complete_on_async_return, kTypeArgsLen,
Object::null_array(), arguments, owner()->ic_data_array(),
owner()->GetNextDeoptId());
owner()->GetNextDeoptId(), ICData::kStatic);
Do(call);
// Rebind the return value for the actual return call to be null.
@@ -2247,7 +2248,7 @@ void EffectGraphVisitor::VisitStringInterpolateNode(
kTypeArgsLen, kNumberOfArguments, kNoArgumentNames));
StaticCallInstr* call = new (Z) StaticCallInstr(
node->token_pos(), function, kTypeArgsLen, kNoArgumentNames, values,
owner()->ic_data_array(), owner()->GetNextDeoptId());
owner()->ic_data_array(), owner()->GetNextDeoptId(), ICData::kStatic);
ReturnDefinition(call);
return;
}
@@ -2476,6 +2477,21 @@ void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
}
}
static ICData::RebindRule ConvertRebindRule(
StaticCallNode::RebindRule rebind_rule_ast) {
switch (rebind_rule_ast) {
case StaticCallNode::kNSMDispatch:
return ICData::kNSMDispatch;
case StaticCallNode::kSuper:
return ICData::kSuper;
case StaticCallNode::kStatic:
return ICData::kStatic;
default:
UNREACHABLE();
return ICData::kStatic;
}
}
// <Expression> ::= StaticCall { function: Function
// arguments: <ArgumentList> }
void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) {
@@ -2487,7 +2503,7 @@ void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) {
StaticCallInstr* call = new (Z) StaticCallInstr(
node->token_pos(), node->function(), node->arguments()->type_args_len(),
node->arguments()->names(), arguments, owner()->ic_data_array(),
owner()->GetNextDeoptId());
owner()->GetNextDeoptId(), ConvertRebindRule(node->rebind_rule()));
if (node->function().recognized_kind() != MethodRecognizer::kUnknown) {
call->set_result_cid(MethodRecognizer::ResultCid(node->function()));
}
@@ -2581,10 +2597,10 @@ void EffectGraphVisitor::BuildConstructorCall(
BuildPushArguments(*node->arguments(), arguments);
const intptr_t kTypeArgsLen = 0;
Do(new (Z)
StaticCallInstr(node->token_pos(), node->constructor(), kTypeArgsLen,
node->arguments()->names(), arguments,
owner()->ic_data_array(), owner()->GetNextDeoptId()));
Do(new (Z) StaticCallInstr(node->token_pos(), node->constructor(),
kTypeArgsLen, node->arguments()->names(),
arguments, owner()->ic_data_array(),
owner()->GetNextDeoptId(), ICData::kStatic));
}
static intptr_t GetResultCidOfListFactory(ConstructorCallNode* node) {
@@ -2621,10 +2637,10 @@ void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) {
ASSERT(arguments->length() == 1);
BuildPushArguments(*node->arguments(), arguments);
const int kTypeArgsLen = 0;
StaticCallInstr* call = new (Z)
StaticCallInstr(node->token_pos(), node->constructor(), kTypeArgsLen,
node->arguments()->names(), arguments,
owner()->ic_data_array(), owner()->GetNextDeoptId());
StaticCallInstr* call = new (Z) StaticCallInstr(
node->token_pos(), node->constructor(), kTypeArgsLen,
node->arguments()->names(), arguments, owner()->ic_data_array(),
owner()->GetNextDeoptId(), ICData::kStatic);
const intptr_t result_cid = GetResultCidOfListFactory(node);
if (result_cid != kDynamicCid) {
call->set_result_cid(result_cid);
@@ -3020,10 +3036,11 @@ void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) {
}
ASSERT(!getter_function.IsNull());
const intptr_t kTypeArgsLen = 0;
StaticCallInstr* call = new (Z) StaticCallInstr(
node->token_pos(), getter_function, kTypeArgsLen,
Object::null_array(), // No names
arguments, owner()->ic_data_array(), owner()->GetNextDeoptId());
StaticCallInstr* call =
new (Z) StaticCallInstr(node->token_pos(), getter_function, kTypeArgsLen,
Object::null_array(), // No names
arguments, owner()->ic_data_array(),
owner()->GetNextDeoptId(), ICData::kStatic);
ReturnDefinition(call);
}
@@ -3085,7 +3102,7 @@ void EffectGraphVisitor::BuildStaticSetter(StaticSetterNode* node,
call = new (Z) StaticCallInstr(token_pos, setter_function, kTypeArgsLen,
Object::null_array(), // No names.
arguments, owner()->ic_data_array(),
owner()->GetNextDeoptId());
owner()->GetNextDeoptId(), ICData::kStatic);
}
if (result_is_needed) {
Do(call);
@@ -3515,7 +3532,8 @@ void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) {
// Generate static call to super operator.
StaticCallInstr* load = new (Z) StaticCallInstr(
node->token_pos(), *super_function, kTypeArgsLen, Object::null_array(),
arguments, owner()->ic_data_array(), owner()->GetNextDeoptId());
arguments, owner()->ic_data_array(), owner()->GetNextDeoptId(),
ICData::kStatic);
ReturnDefinition(load);
} else {
// Generate dynamic call to index operator.
@@ -3588,7 +3606,8 @@ Definition* EffectGraphVisitor::BuildStoreIndexedValues(StoreIndexedNode* node,
StaticCallInstr* store = new (Z) StaticCallInstr(
token_pos, *super_function, kTypeArgsLen, Object::null_array(),
arguments, owner()->ic_data_array(), owner()->GetNextDeoptId());
arguments, owner()->ic_data_array(), owner()->GetNextDeoptId(),
ICData::kStatic);
if (result_is_needed) {
Do(store);
return BuildLoadExprTemp(token_pos);
@@ -3796,7 +3815,8 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
type_args_val = Bind(new (Z) StaticCallInstr(
node->token_pos(), prepend_function, kTypeArgsLen,
Object::null_array(), // No names.
arguments, owner()->ic_data_array(), owner()->GetNextDeoptId()));
arguments, owner()->ic_data_array(), owner()->GetNextDeoptId(),
ICData::kStatic));
}
Do(BuildStoreLocal(*type_args_var, type_args_val, ST(node->token_pos())));
if (type_args_var->is_captured()) {
@@ -3838,11 +3858,12 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
ASSERT(!async_set_thread_stack_trace.IsNull());
// Call _asyncSetThreadStackTrace
const intptr_t kTypeArgsLen = 0;
StaticCallInstr* call_async_set_thread_stack_trace = new (Z)
StaticCallInstr(node->token_pos().ToSynthetic(),
async_set_thread_stack_trace, kTypeArgsLen,
Object::null_array(), arguments,
owner()->ic_data_array(), owner()->GetNextDeoptId());
StaticCallInstr* call_async_set_thread_stack_trace =
new (Z) StaticCallInstr(node->token_pos().ToSynthetic(),
async_set_thread_stack_trace, kTypeArgsLen,
Object::null_array(), arguments,
owner()->ic_data_array(),
owner()->GetNextDeoptId(), ICData::kStatic);
Do(call_async_set_thread_stack_trace);
}
@@ -4199,9 +4220,10 @@ StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall(
ZoneGrowableArray<PushArgumentInstr*>* push_arguments =
new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
BuildPushArguments(*args, push_arguments);
return new (Z) StaticCallInstr(
args_pos, no_such_method_func, kTypeArgsLen, Object::null_array(),
push_arguments, owner()->ic_data_array(), owner()->GetNextDeoptId());
return new (Z) StaticCallInstr(args_pos, no_such_method_func, kTypeArgsLen,
Object::null_array(), push_arguments,
owner()->ic_data_array(),
owner()->GetNextDeoptId(), ICData::kStatic);
}
StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError(
@@ -4267,7 +4289,7 @@ StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError(
return new (Z) StaticCallInstr(token_pos, func, kTypeArgsLen,
Object::null_array(), // No names.
arguments, owner()->ic_data_array(),
owner()->GetNextDeoptId());
owner()->GetNextDeoptId(), ICData::kStatic);
}
void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) {
@@ -3408,8 +3408,9 @@ Fragment StreamingFlowGraphBuilder::BuildInitializers(
const Function& target = Function::ZoneHandle(
Z, H.LookupConstructorByKernelConstructor(canonical_target));
instructions += StaticCall(TokenPosition::kNoSource, target,
argument_count, argument_names);
instructions +=
StaticCall(TokenPosition::kNoSource, target, argument_count,
argument_names, ICData::kStatic);
instructions += Drop();
break;
}
@@ -3429,8 +3430,9 @@ Fragment StreamingFlowGraphBuilder::BuildInitializers(
const Function& target = Function::ZoneHandle(
Z, H.LookupConstructorByKernelConstructor(canonical_target));
instructions += StaticCall(TokenPosition::kNoSource, target,
argument_count, argument_names);
instructions +=
StaticCall(TokenPosition::kNoSource, target, argument_count,
argument_names, ICData::kStatic);
instructions += Drop();
break;
}
@@ -3538,7 +3540,7 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
intptr_t argument_count = positional_argument_count + named_argument_count;
if (!target.is_static()) ++argument_count;
body += StaticCall(TokenPosition::kNoSource, target, argument_count,
argument_names);
argument_names, ICData::kNoRebind);
// Return the result.
body += Return(function_node_helper.end_position_);
@@ -3829,7 +3831,8 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction(bool constructor) {
instructions += PushArgument();
// Call _asyncSetThreadStackTrace
instructions += StaticCall(TokenPosition::kNoSource, target, 1);
instructions += StaticCall(TokenPosition::kNoSource, target,
/* argument_count = */ 1, ICData::kStatic);
instructions += Drop();
// TODO(29737): This sequence should be generated in order.
@@ -4995,17 +4998,21 @@ Fragment StreamingFlowGraphBuilder::LoadStaticField() {
Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count) {
return flow_graph_builder_->StaticCall(position, target, argument_count);
intptr_t argument_count,
ICData::RebindRule rebind_rule) {
return flow_graph_builder_->StaticCall(position, target, argument_count,
rebind_rule);
}
Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count,
const Array& argument_names,
ICData::RebindRule rebind_rule,
intptr_t type_args_count) {
return flow_graph_builder_->StaticCall(position, target, argument_count,
argument_names, type_args_count);
argument_names, rebind_rule,
type_args_count);
}
Fragment StreamingFlowGraphBuilder::InstanceCall(
@@ -5463,7 +5470,12 @@ Fragment StreamingFlowGraphBuilder::BuildDirectPropertyGet(TokenPosition* p) {
}
instructions += PushArgument();
return instructions + StaticCall(position, target, 1);
// Static calls are marked as "no-rebind", which is currently safe because
// DirectPropertyGet are only used in enums (index in toString) and enums
// can't change their structure during hot reload.
// If there are other sources of DirectPropertyGet in the future, this code
// have to be adjusted.
return instructions + StaticCall(position, target, 1, ICData::kNoRebind);
}
Fragment StreamingFlowGraphBuilder::BuildDirectPropertySet(TokenPosition* p) {
@@ -5487,7 +5499,12 @@ Fragment StreamingFlowGraphBuilder::BuildDirectPropertySet(TokenPosition* p) {
instructions += StoreLocal(TokenPosition::kNoSource, value);
instructions += PushArgument();
instructions += StaticCall(position, target, 2);
// Static calls are marked as "no-rebind", which is currently safe because
// DirectPropertyGet are only used in enums (index in toString) and enums
// can't change their structure during hot reload.
// If there are other sources of DirectPropertyGet in the future, this code
// have to be adjusted.
instructions += StaticCall(position, target, 2, ICData::kNoRebind);
return instructions + Drop();
}
@@ -5514,7 +5531,7 @@ Fragment StreamingFlowGraphBuilder::BuildStaticGet(TokenPosition* p) {
Fragment instructions = Constant(field);
return instructions + LoadStaticField();
} else {
return StaticCall(position, getter, 0);
return StaticCall(position, getter, 0, ICData::kStatic);
}
}
} else {
@@ -5522,7 +5539,7 @@ Fragment StreamingFlowGraphBuilder::BuildStaticGet(TokenPosition* p) {
Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
if (H.IsGetter(target)) {
return StaticCall(position, function, 0);
return StaticCall(position, function, 0, ICData::kStatic);
} else if (H.IsMethod(target)) {
return Constant(constant_evaluator_.EvaluateExpression(offset));
} else {
@@ -5566,7 +5583,7 @@ Fragment StreamingFlowGraphBuilder::BuildStaticSet(TokenPosition* p) {
// Invoke the setter function.
const Function& function =
Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
instructions += StaticCall(position, function, 1);
instructions += StaticCall(position, function, 1, ICData::kStatic);
// Drop the unused result & leave the stored value on the stack.
return instructions + Drop();
@@ -5721,7 +5738,8 @@ Fragment StreamingFlowGraphBuilder::BuildDirectMethodInvocation(
BuildArguments(&argument_names, &argument_count); // read arguments.
++argument_count;
return instructions + StaticCall(TokenPosition::kNoSource, target,
argument_count, argument_names);
argument_count, argument_names,
ICData::kNoRebind);
}
Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
@@ -5799,8 +5817,8 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
ASSERT(argument_count == 2);
instructions += StrictCompare(Token::kEQ_STRICT, /*number_check=*/true);
} else {
instructions +=
StaticCall(position, target, argument_count, argument_names);
instructions += StaticCall(position, target, argument_count, argument_names,
ICData::kStatic);
if (target.IsGenerativeConstructor()) {
// Drop the result of the constructor call and leave [instance_variable]
// on top-of-stack.
@@ -5897,7 +5915,8 @@ Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation(
const Function& target = Function::ZoneHandle(
Z, H.LookupConstructorByKernelConstructor(klass, kernel_name));
++argument_count;
instructions += StaticCall(position, target, argument_count, argument_names);
instructions += StaticCall(position, target, argument_count, argument_names,
ICData::kStatic);
return instructions + Drop();
}
@@ -6261,7 +6280,8 @@ Fragment StreamingFlowGraphBuilder::BuildListLiteral(bool is_const,
Z, factory_class.LookupFactory(
Library::PrivateCoreLibName(Symbols::ListLiteralFactory())));
return instructions + StaticCall(position, factory_method, 2);
return instructions +
StaticCall(position, factory_method, 2, ICData::kStatic);
}
Fragment StreamingFlowGraphBuilder::BuildMapLiteral(bool is_const,
@@ -6321,7 +6341,8 @@ Fragment StreamingFlowGraphBuilder::BuildMapLiteral(bool is_const,
Z, map_class.LookupFactory(
Library::PrivateCoreLibName(Symbols::MapLiteralFactory())));
return instructions + StaticCall(position, factory_method, 2);
return instructions +
StaticCall(position, factory_method, 2, ICData::kStatic);
}
Fragment StreamingFlowGraphBuilder::BuildFunctionExpression() {
@@ -6593,7 +6614,8 @@ Fragment StreamingFlowGraphBuilder::BuildAssertStatement() {
}
otherwise_fragment += PushArgument(); // message
otherwise_fragment += StaticCall(TokenPosition::kNoSource, target, 3);
otherwise_fragment +=
StaticCall(TokenPosition::kNoSource, target, 3, ICData::kStatic);
otherwise_fragment += Drop();
return Fragment(instructions.entry, then);
@@ -6900,7 +6922,8 @@ Fragment StreamingFlowGraphBuilder::BuildSwitchStatement() {
body_fragment += NullConstant();
body_fragment += PushArgument(); // line
body_fragment += StaticCall(TokenPosition::kNoSource, constructor, 3);
body_fragment +=
StaticCall(TokenPosition::kNoSource, constructor, 3, ICData::kStatic);
body_fragment += Drop();
// Throw the exception
@@ -952,11 +952,13 @@ class StreamingFlowGraphBuilder {
Fragment LoadStaticField();
Fragment StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count);
intptr_t argument_count,
ICData::RebindRule rebind_rule);
Fragment StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count,
const Array& argument_names,
ICData::RebindRule rebind_rule,
intptr_t type_args_len = 0);
Fragment InstanceCall(TokenPosition position,
const String& name,
+22 -12
View File
@@ -1239,7 +1239,8 @@ Fragment FlowGraphBuilder::Return(TokenPosition position) {
const Function& target = Function::ZoneHandle(
Z, I->object_store()->async_clear_thread_stack_trace());
ASSERT(!target.IsNull());
instructions += StaticCall(TokenPosition::kNoSource, target, 0);
instructions += StaticCall(TokenPosition::kNoSource, target,
/* argument_count = */ 0, ICData::kStatic);
instructions += Drop();
}
@@ -1254,8 +1255,10 @@ Fragment FlowGraphBuilder::Return(TokenPosition position) {
Fragment FlowGraphBuilder::StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count) {
return StaticCall(position, target, argument_count, Array::null_array());
intptr_t argument_count,
ICData::RebindRule rebind_rule) {
return StaticCall(position, target, argument_count, Array::null_array(),
rebind_rule);
}
static intptr_t GetResultCidOfListFactory(Zone* zone,
@@ -1283,11 +1286,12 @@ Fragment FlowGraphBuilder::StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count,
const Array& argument_names,
ICData::RebindRule rebind_rule,
intptr_t type_args_count) {
ArgumentArray arguments = GetArguments(argument_count);
StaticCallInstr* call =
new (Z) StaticCallInstr(position, target, type_args_count, argument_names,
arguments, ic_data_array_, GetNextDeoptId());
StaticCallInstr* call = new (Z)
StaticCallInstr(position, target, type_args_count, argument_names,
arguments, ic_data_array_, GetNextDeoptId(), rebind_rule);
const intptr_t list_cid =
GetResultCidOfListFactory(Z, target, argument_count);
if (list_cid != kDynamicCid) {
@@ -1412,7 +1416,8 @@ Fragment FlowGraphBuilder::StringInterpolateSingle(TokenPosition position) {
kTypeArgsLen, kNumberOfArguments, kNoArgumentNames));
Fragment instructions;
instructions += PushArgument();
instructions += StaticCall(position, function, 1);
instructions +=
StaticCall(position, function, /* argument_count = */ 1, ICData::kStatic);
return instructions;
}
@@ -1451,7 +1456,8 @@ Fragment FlowGraphBuilder::ThrowTypeError() {
instructions += Constant(H.DartSymbol("Malformed type."));
instructions += PushArgument(); // message
instructions += StaticCall(TokenPosition::kNoSource, constructor, 5);
instructions += StaticCall(TokenPosition::kNoSource, constructor,
/* argument_count = */ 5, ICData::kStatic);
instructions += Drop();
// Throw the exception
@@ -1490,7 +1496,8 @@ Fragment FlowGraphBuilder::ThrowNoSuchMethodError() {
instructions += NullConstant();
instructions += PushArgument(); // existingArgumentNames
instructions += StaticCall(TokenPosition::kNoSource, throw_function, 6);
instructions += StaticCall(TokenPosition::kNoSource, throw_function,
/* argument_count = */ 6, ICData::kStatic);
// Leave "result" on the stack since callers expect it to be there (even
// though the function will result in an exception).
@@ -1858,7 +1865,8 @@ Fragment FlowGraphBuilder::EvaluateAssertion() {
Function::ZoneHandle(Z, klass.LookupStaticFunctionAllowPrivate(
H.DartSymbol("_evaluateAssertion")));
ASSERT(!target.IsNull());
return StaticCall(TokenPosition::kNoSource, target, 1);
return StaticCall(TokenPosition::kNoSource, target, /* argument_count = */ 1,
ICData::kStatic);
}
Fragment FlowGraphBuilder::CheckReturnTypeInCheckedMode() {
@@ -2037,7 +2045,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher(
Z, mirror_class.LookupStaticFunction(
Library::PrivateCoreLibName(Symbols::AllocateInvocationMirror())));
ASSERT(!allocation_function.IsNull());
body += StaticCall(TokenPosition::kMinSource, allocation_function, 4);
body += StaticCall(TokenPosition::kMinSource, allocation_function,
/* argument_count = */ 4, ICData::kStatic);
body += PushArgument(); // For the call to noSuchMethod.
const int kTypeArgsLen = 0;
@@ -2054,7 +2063,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher(
Class::Handle(Z, I->object_store()->object_class()),
Symbols::NoSuchMethod(), two_arguments);
}
body += StaticCall(TokenPosition::kMinSource, no_such_method, 2);
body += StaticCall(TokenPosition::kMinSource, no_such_method,
/* argument_count = */ 2, ICData::kNSMDispatch);
body += Return(TokenPosition::kNoSource);
return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
+3 -1
View File
@@ -560,11 +560,13 @@ class FlowGraphBuilder {
Fragment Return(TokenPosition position);
Fragment StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count);
intptr_t argument_count,
ICData::RebindRule rebind_rule);
Fragment StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count,
const Array& argument_names,
ICData::RebindRule rebind_rule,
intptr_t type_args_len = 0);
Fragment StoreIndexed(intptr_t class_id);
Fragment StoreInstanceFieldGuarded(const Field& field,
+13 -9
View File
@@ -12877,13 +12877,17 @@ void ICData::AddDeoptReason(DeoptReasonId reason) const {
}
}
void ICData::SetIsStaticCall(bool static_call) const {
ICData::RebindRule ICData::rebind_rule() const {
return (ICData::RebindRule)RebindRuleBits::decode(raw_ptr()->state_bits_);
}
void ICData::set_rebind_rule(uint32_t rebind_rule) const {
StoreNonPointer(&raw_ptr()->state_bits_,
StaticCallBit::update(static_call, raw_ptr()->state_bits_));
RebindRuleBits::update(rebind_rule, raw_ptr()->state_bits_));
}
bool ICData::is_static_call() const {
return StaticCallBit::decode(raw_ptr()->state_bits_);
return rebind_rule() != kInstance;
}
void ICData::set_state_bits(uint32_t bits) const {
@@ -13673,7 +13677,7 @@ RawICData* ICData::NewDescriptor(Zone* zone,
const Array& arguments_descriptor,
intptr_t deopt_id,
intptr_t num_args_tested,
bool is_static_call) {
RebindRule rebind_rule) {
ASSERT(!owner.IsNull());
ASSERT(!target_name.IsNull());
ASSERT(!arguments_descriptor.IsNull());
@@ -13695,7 +13699,7 @@ RawICData* ICData::NewDescriptor(Zone* zone,
#if defined(TAG_IC_DATA)
result.set_tag(-1);
#endif
result.SetIsStaticCall(is_static_call);
result.set_rebind_rule(rebind_rule);
result.SetNumArgsTested(num_args_tested);
return result.raw();
}
@@ -13727,11 +13731,11 @@ RawICData* ICData::New(const Function& owner,
const Array& arguments_descriptor,
intptr_t deopt_id,
intptr_t num_args_tested,
bool is_static_call) {
RebindRule rebind_rule) {
Zone* zone = Thread::Current()->zone();
const ICData& result = ICData::Handle(
zone, NewDescriptor(zone, owner, target_name, arguments_descriptor,
deopt_id, num_args_tested, is_static_call));
deopt_id, num_args_tested, rebind_rule));
result.set_ic_data_array(
Array::Handle(zone, CachedEmptyICDataArray(num_args_tested)));
return result.raw();
@@ -13741,7 +13745,7 @@ RawICData* ICData::NewFrom(const ICData& from, intptr_t num_args_tested) {
const ICData& result = ICData::Handle(ICData::New(
Function::Handle(from.Owner()), String::Handle(from.target_name()),
Array::Handle(from.arguments_descriptor()), from.deopt_id(),
num_args_tested, from.is_static_call()));
num_args_tested, from.rebind_rule()));
// Copy deoptimization reasons.
result.SetDeoptReasons(from.DeoptReasons());
return result.raw();
@@ -13753,7 +13757,7 @@ RawICData* ICData::Clone(const ICData& from) {
zone, Function::Handle(zone, from.Owner()),
String::Handle(zone, from.target_name()),
Array::Handle(zone, from.arguments_descriptor()), from.deopt_id(),
from.NumArgsTested(), from.is_static_call()));
from.NumArgsTested(), from.rebind_rule()));
// Clone entry array.
const Array& from_array = Array::Handle(zone, from.ic_data());
const intptr_t len = from_array.Length();
+24 -9
View File
@@ -1748,6 +1748,20 @@ class ICData : public Object {
bool HasDeoptReason(ICData::DeoptReasonId reason) const;
void AddDeoptReason(ICData::DeoptReasonId reason) const;
// Call site classification that is helpful for hot-reload. Call sites with
// different `RebindRule` have to be rebound differently.
enum RebindRule {
kInstance,
kNoRebind,
kNSMDispatch,
kOptimized,
kStatic,
kSuper,
kNumRebindRules,
};
RebindRule rebind_rule() const;
void set_rebind_rule(uint32_t rebind_rule) const;
// The length of the array. This includes all sentinel entries including
// the final one.
intptr_t Length() const;
@@ -1887,7 +1901,7 @@ class ICData : public Object {
const Array& arguments_descriptor,
intptr_t deopt_id,
intptr_t num_args_tested,
bool is_static_call);
RebindRule rebind_rule);
static RawICData* NewFrom(const ICData& from, intptr_t num_args_tested);
// Generates a new ICData with descriptor and data array copied (deep clone).
@@ -1921,7 +1935,6 @@ class ICData : public Object {
intptr_t tag() const { return raw_ptr()->tag_; }
#endif
void SetIsStaticCall(bool static_call) const;
bool is_static_call() const;
private:
@@ -1944,10 +1957,12 @@ class ICData : public Object {
kNumArgsTestedSize = 2,
kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize,
kDeoptReasonSize = kLastRecordedDeoptReason + 1,
kStaticCallPos = kDeoptReasonPos + kDeoptReasonSize,
kStaticCallSize = 1,
kRebindRulePos = kDeoptReasonPos + kDeoptReasonSize,
kRebindRuleSize = 3
};
COMPILE_ASSERT(kNumRebindRules <= (1 << kRebindRuleSize));
class NumArgsTestedBits : public BitField<uint32_t,
uint32_t,
kNumArgsTestedPos,
@@ -1956,10 +1971,10 @@ class ICData : public Object {
uint32_t,
ICData::kDeoptReasonPos,
ICData::kDeoptReasonSize> {};
class StaticCallBit : public BitField<uint32_t,
bool,
ICData::kStaticCallPos,
ICData::kStaticCallSize> {};
class RebindRuleBits : public BitField<uint32_t,
uint32_t,
ICData::kRebindRulePos,
ICData::kRebindRuleSize> {};
#if defined(DEBUG)
// Used in asserts to verify that a check is not added twice.
bool HasCheck(const GrowableArray<intptr_t>& cids) const;
@@ -1974,7 +1989,7 @@ class ICData : public Object {
const Array& arguments_descriptor,
intptr_t deopt_id,
intptr_t num_args_tested,
bool is_static_call);
RebindRule rebind_rule);
static void WriteSentinel(const Array& data, intptr_t test_entry_length);
+26 -38
View File
@@ -687,7 +687,22 @@ void Library::CheckReload(const Library& replacement,
static const Function* static_call_target = NULL;
void ICData::Reset(Zone* zone) const {
if (is_static_call()) {
RebindRule rule = rebind_rule();
if (rule == kInstance) {
intptr_t num_args = NumArgsTested();
if (num_args == 2) {
ClearWithSentinel();
} else {
const Array& data_array =
Array::Handle(zone, CachedEmptyICDataArray(num_args));
set_ic_data_array(data_array);
}
return;
} else if (rule == kNoRebind || rule == kNSMDispatch) {
// TODO(30877) we should account for addition/removal of NSM.
// Don't rebind dispatchers.
return;
} else if (rule == kStatic || rule == kSuper) {
const Function& old_target = Function::Handle(zone, GetTargetAt(0));
if (old_target.IsNull()) {
FATAL("old_target is NULL.\n");
@@ -696,34 +711,19 @@ void ICData::Reset(Zone* zone) const {
const String& selector = String::Handle(zone, old_target.name());
Function& new_target = Function::Handle(zone);
if (!old_target.is_static()) {
if (old_target.kind() == RawFunction::kConstructor) {
return; // Super constructor call.
}
if (rule == kStatic) {
ASSERT(old_target.is_static() ||
old_target.kind() == RawFunction::kConstructor);
// This can be incorrect if the call site was an unqualified invocation.
const Class& cls = Class::Handle(zone, old_target.Owner());
new_target = cls.LookupStaticFunction(selector);
} else {
// Super call.
Function& caller = Function::Handle(zone);
caller ^= Owner();
ASSERT(!caller.is_static());
Class& cls = Class::Handle(zone, caller.Owner());
if (cls.raw() == old_target.Owner()) {
// Dispatcher.
if (caller.IsImplicitClosureFunction()) {
return; // Tear-off.
}
if (caller.kind() == RawFunction::kNoSuchMethodDispatcher) {
// TODO(rmacnak): noSuchMethod might have been redefined.
return;
}
const Function& caller_parent =
Function::Handle(zone, caller.parent_function());
if (!caller_parent.IsNull()) {
if (caller_parent.kind() == RawFunction::kInvokeFieldDispatcher) {
return; // Call-through-getter.
}
}
FATAL2("Unexpected dispatcher-like call site: %s from %s\n",
selector.ToCString(), caller.ToQualifiedCString());
}
// Super call.
cls = cls.SuperClass();
while (!cls.IsNull()) {
// TODO(rmacnak): Should use Resolver::ResolveDynamicAnyArgs to handle
@@ -735,12 +735,7 @@ void ICData::Reset(Zone* zone) const {
}
cls = cls.SuperClass();
}
} else {
// This can be incorrect if the call site was an unqualified invocation.
const Class& cls = Class::Handle(zone, old_target.Owner());
new_target = cls.LookupStaticFunction(selector);
}
const Array& args_desc_array = Array::Handle(zone, arguments_descriptor());
ArgumentsDescriptor args_desc(args_desc_array);
if (new_target.IsNull() || !new_target.AreValidArguments(args_desc, NULL)) {
@@ -752,14 +747,7 @@ void ICData::Reset(Zone* zone) const {
}
ClearAndSetStaticTarget(new_target);
} else {
intptr_t num_args = NumArgsTested();
if (num_args == 2) {
ClearWithSentinel();
} else {
const Array& data_array =
Array::Handle(zone, CachedEmptyICDataArray(num_args));
set_ic_data_array(data_array);
}
FATAL("Unexpected rebind rule.");
}
}
+6 -4
View File
@@ -2987,7 +2987,7 @@ ISOLATE_UNIT_TEST_CASE(ICData) {
ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs, Object::null_array()));
ICData& o1 = ICData::Handle();
o1 = ICData::New(function, target_name, args_descriptor, id, num_args_tested,
false);
ICData::kInstance);
EXPECT_EQ(1, o1.NumArgsTested());
EXPECT_EQ(id, o1.deopt_id());
EXPECT_EQ(function.raw(), o1.Owner());
@@ -3026,7 +3026,8 @@ ISOLATE_UNIT_TEST_CASE(ICData) {
EXPECT_EQ(2, o1.NumberOfUsedChecks());
ICData& o2 = ICData::Handle();
o2 = ICData::New(function, target_name, args_descriptor, 57, 2, false);
o2 = ICData::New(function, target_name, args_descriptor, 57, 2,
ICData::kInstance);
EXPECT_EQ(2, o2.NumArgsTested());
EXPECT_EQ(57, o2.deopt_id());
EXPECT_EQ(function.raw(), o2.Owner());
@@ -3044,8 +3045,9 @@ ISOLATE_UNIT_TEST_CASE(ICData) {
// Check ICData for unoptimized static calls.
const intptr_t kNumArgsChecked = 0;
const ICData& scall_icdata = ICData::Handle(ICData::New(
function, target_name, args_descriptor, 57, kNumArgsChecked, false));
const ICData& scall_icdata =
ICData::Handle(ICData::New(function, target_name, args_descriptor, 57,
kNumArgsChecked, ICData::kInstance));
scall_icdata.AddTarget(target1);
EXPECT_EQ(target1.raw(), scall_icdata.GetTargetAt(0));
}
+46 -31
View File
@@ -1626,7 +1626,8 @@ SequenceNode* Parser::ParseImplicitClosure(const Function& func) {
// receiver.
if (!target.IsNull() &&
(parent.num_fixed_parameters() == target.num_fixed_parameters())) {
call = new StaticCallNode(token_pos, target, func_args);
call = new StaticCallNode(token_pos, target, func_args,
StaticCallNode::kStatic);
} else if (!parent.is_static()) {
NOT_IN_PRODUCT(ASSERT(Isolate::Current()->HasAttemptedReload()));
// If a subsequent reload reintroduces the target in the middle of the
@@ -1649,7 +1650,8 @@ SequenceNode* Parser::ParseImplicitClosure(const Function& func) {
Class::Handle(Z, I->object_store()->object_class()),
Symbols::NoSuchMethod(), args_desc);
}
call = new StaticCallNode(token_pos, no_such_method, arguments);
call = new StaticCallNode(token_pos, no_such_method, arguments,
StaticCallNode::kStatic);
} else {
NOT_IN_PRODUCT(ASSERT(Isolate::Current()->HasAttemptedReload()));
// If a subsequent reload reintroduces the target in the middle of the
@@ -1804,8 +1806,8 @@ SequenceNode* Parser::ParseNoSuchMethodDispatcher(const Function& func) {
Class::Handle(Z, I->object_store()->object_class()),
Symbols::NoSuchMethod(), args_desc);
}
StaticCallNode* call =
new StaticCallNode(token_pos, no_such_method, arguments);
StaticCallNode* call = new StaticCallNode(
token_pos, no_such_method, arguments, StaticCallNode::kNSMDispatch);
ReturnNode* return_node = new ReturnNode(token_pos, call);
current_block_->statements->Add(return_node);
@@ -2452,7 +2454,8 @@ StaticCallNode* Parser::BuildInvocationMirrorAllocation(
Function::ZoneHandle(mirror_class.LookupStaticFunction(
Library::PrivateCoreLibName(Symbols::AllocateInvocationMirror())));
ASSERT(!allocation_function.IsNull());
return new StaticCallNode(call_pos, allocation_function, arguments);
return new StaticCallNode(call_pos, allocation_function, arguments,
StaticCallNode::kStatic);
}
ArgumentListNode* Parser::BuildNoSuchMethodArguments(
@@ -2508,7 +2511,8 @@ AstNode* Parser::ParseSuperCall(const String& function_name,
arguments = BuildNoSuchMethodArguments(supercall_pos, function_name,
*arguments, NULL, true);
}
return new StaticCallNode(supercall_pos, super_function, arguments);
return new StaticCallNode(supercall_pos, super_function, arguments,
StaticCallNode::kSuper);
}
// Simple test if a node is side effect free.
@@ -2535,7 +2539,8 @@ AstNode* Parser::BuildUnarySuperOperator(Token::Kind op, PrimaryNode* super) {
op_arguments = BuildNoSuchMethodArguments(
super_pos, operator_function_name, *op_arguments, NULL, true);
}
super_op = new StaticCallNode(super_pos, super_operator, op_arguments);
super_op = new StaticCallNode(super_pos, super_operator, op_arguments,
StaticCallNode::kSuper);
} else {
ReportError(super_pos, "illegal super operator call");
}
@@ -2588,7 +2593,8 @@ AstNode* Parser::ParseSuperOperator() {
op_arguments = BuildNoSuchMethodArguments(
operator_pos, operator_function_name, *op_arguments, NULL, true);
}
super_op = new StaticCallNode(operator_pos, super_operator, op_arguments);
super_op = new StaticCallNode(operator_pos, super_operator, op_arguments,
StaticCallNode::kSuper);
if (negate_result) {
super_op = new UnaryOpNode(operator_pos, Token::kNOT, super_op);
}
@@ -2715,7 +2721,8 @@ StaticCallNode* Parser::GenerateSuperConstructorCall(
String::Handle(Z, super_class.Name()).ToCString(),
error_message.ToCString());
}
return new StaticCallNode(supercall_pos, super_ctor, arguments);
return new StaticCallNode(supercall_pos, super_ctor, arguments,
StaticCallNode::kSuper);
}
StaticCallNode* Parser::ParseSuperInitializer(const Class& cls,
@@ -2769,7 +2776,8 @@ StaticCallNode* Parser::ParseSuperInitializer(const Class& cls,
"invalid arguments passed to super class constructor '%s': %s",
ctor_name.ToCString(), error_message.ToCString());
}
return new StaticCallNode(supercall_pos, super_ctor, arguments);
return new StaticCallNode(supercall_pos, super_ctor, arguments,
StaticCallNode::kSuper);
}
AstNode* Parser::ParseInitializer(const Class& cls,
@@ -3163,8 +3171,8 @@ void Parser::ParseConstructorRedirection(const Class& cls,
String::Handle(Z, redirect_ctor.UserVisibleName()).ToCString(),
error_message.ToCString());
}
current_block_->statements->Add(
new StaticCallNode(call_pos, redirect_ctor, arguments));
current_block_->statements->Add(new StaticCallNode(
call_pos, redirect_ctor, arguments, StaticCallNode::kStatic));
}
SequenceNode* Parser::MakeImplicitConstructor(const Function& func) {
@@ -7371,8 +7379,9 @@ SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure_func,
new (Z) ArgumentListNode(TokenPosition::kNoSource);
async_stack_trace_helper_args->Add(
new (Z) LoadLocalNode(TokenPosition::kNoSource, async_op_var));
StaticCallNode* async_stack_trace_helper_call = new (Z) StaticCallNode(
token_pos, async_stack_trace_helper, async_stack_trace_helper_args);
StaticCallNode* async_stack_trace_helper_call = new (Z)
StaticCallNode(token_pos, async_stack_trace_helper,
async_stack_trace_helper_args, StaticCallNode::kStatic);
LocalVariable* async_stack_trace_var =
current_block_->scope->LookupVariable(Symbols::AsyncStackTraceVar(),
false);
@@ -7392,7 +7401,7 @@ SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure_func,
new (Z) LoadLocalNode(TokenPosition::kNoSource, async_op_var));
StaticCallNode* then_wrapper_call = new (Z)
StaticCallNode(TokenPosition::kNoSource, async_then_wrapper_helper,
async_then_wrapper_helper_args);
async_then_wrapper_helper_args, StaticCallNode::kStatic);
LocalVariable* async_then_callback_var =
current_block_->scope->LookupVariable(Symbols::AsyncThenCallback(),
false);
@@ -7413,7 +7422,7 @@ SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure_func,
new (Z) LoadLocalNode(TokenPosition::kNoSource, async_op_var));
StaticCallNode* error_wrapper_call = new (Z)
StaticCallNode(TokenPosition::kNoSource, async_error_wrapper_helper,
async_error_wrapper_helper_args);
async_error_wrapper_helper_args, StaticCallNode::kStatic);
LocalVariable* async_catch_error_callback_var =
current_block_->scope->LookupVariable(Symbols::AsyncCatchErrorCallback(),
false);
@@ -7590,8 +7599,9 @@ SequenceNode* Parser::CloseAsyncFunction(const Function& closure,
new (Z) ArgumentListNode(token_pos);
async_stack_trace_helper_args->Add(
new (Z) LoadLocalNode(token_pos, async_op_var));
StaticCallNode* async_stack_trace_helper_call = new (Z) StaticCallNode(
token_pos, async_stack_trace_helper, async_stack_trace_helper_args);
StaticCallNode* async_stack_trace_helper_call = new (Z)
StaticCallNode(token_pos, async_stack_trace_helper,
async_stack_trace_helper_args, StaticCallNode::kStatic);
LocalVariable* async_stack_trace_var =
current_block_->scope->LookupVariable(Symbols::AsyncStackTraceVar(),
false);
@@ -7609,8 +7619,9 @@ SequenceNode* Parser::CloseAsyncFunction(const Function& closure,
new (Z) ArgumentListNode(token_pos);
async_then_wrapper_helper_args->Add(
new (Z) LoadLocalNode(token_pos, async_op_var));
StaticCallNode* then_wrapper_call = new (Z) StaticCallNode(
token_pos, async_then_wrapper_helper, async_then_wrapper_helper_args);
StaticCallNode* then_wrapper_call = new (Z)
StaticCallNode(token_pos, async_then_wrapper_helper,
async_then_wrapper_helper_args, StaticCallNode::kStatic);
LocalVariable* async_then_callback_var =
current_block_->scope->LookupVariable(Symbols::AsyncThenCallback(),
false);
@@ -7629,8 +7640,9 @@ SequenceNode* Parser::CloseAsyncFunction(const Function& closure,
new (Z) ArgumentListNode(token_pos);
async_error_wrapper_helper_args->Add(
new (Z) LoadLocalNode(token_pos, async_op_var));
StaticCallNode* error_wrapper_call = new (Z) StaticCallNode(
token_pos, async_error_wrapper_helper, async_error_wrapper_helper_args);
StaticCallNode* error_wrapper_call = new (Z)
StaticCallNode(token_pos, async_error_wrapper_helper,
async_error_wrapper_helper_args, StaticCallNode::kStatic);
LocalVariable* async_catch_error_callback_var =
current_block_->scope->LookupVariable(Symbols::AsyncCatchErrorCallback(),
false);
@@ -9110,8 +9122,8 @@ AstNode* Parser::DartPrint(const char* str) {
new (Z) ArgumentListNode(TokenPosition::kNoSource);
String& msg = String::ZoneHandle(Symbols::NewFormatted(T, "%s", str));
one_arg->Add(new (Z) LiteralNode(TokenPosition::kNoSource, msg));
AstNode* print_call =
new (Z) StaticCallNode(TokenPosition::kNoSource, print_fn, one_arg);
AstNode* print_call = new (Z) StaticCallNode(
TokenPosition::kNoSource, print_fn, one_arg, StaticCallNode::kStatic);
return print_call;
}
@@ -9193,8 +9205,9 @@ AstNode* Parser::ParseAwaitForStatement(String* label_name) {
new (Z) LoadLocalNode(stream_expr_pos, stream_var));
async_star_listen_helper_args->Add(
new (Z) LoadLocalNode(stream_expr_pos, async_op_var));
StaticCallNode* async_star_listen_helper_call = new (Z) StaticCallNode(
stream_expr_pos, async_star_listen_helper, async_star_listen_helper_args);
StaticCallNode* async_star_listen_helper_call = new (Z)
StaticCallNode(stream_expr_pos, async_star_listen_helper,
async_star_listen_helper_args, StaticCallNode::kStatic);
current_block_->statements->Add(async_star_listen_helper_call);
@@ -9264,9 +9277,9 @@ AstNode* Parser::ParseAwaitForStatement(String* label_name) {
new (Z) ArgumentListNode(stream_expr_pos);
async_star_move_next_helper_args->Add(
new (Z) LoadLocalNode(stream_expr_pos, stream_var));
StaticCallNode* async_star_move_next_helper_call =
new (Z) StaticCallNode(stream_expr_pos, async_star_move_next_helper,
async_star_move_next_helper_args);
StaticCallNode* async_star_move_next_helper_call = new (Z)
StaticCallNode(stream_expr_pos, async_star_move_next_helper,
async_star_move_next_helper_args, StaticCallNode::kStatic);
current_block_->statements->Add(async_star_move_next_helper_call);
#endif
AstNode* await_moveNext = new (Z) AwaitNode(
@@ -9626,7 +9639,8 @@ AstNode* Parser::MakeStaticCall(const String& cls_name,
Z, Resolver::ResolveStatic(cls, func_name, kTypeArgsLen,
arguments->length(), arguments->names()));
ASSERT(!func.IsNull());
return new (Z) StaticCallNode(arguments->token_pos(), func, arguments);
return new (Z) StaticCallNode(arguments->token_pos(), func, arguments,
StaticCallNode::kStatic);
}
AstNode* Parser::ParseAssertStatement(bool is_const) {
@@ -11682,7 +11696,8 @@ AstNode* Parser::ParseStaticCall(const Class& cls,
return new (Z) ComparisonNode(ident_pos, Token::kEQ_STRICT,
arguments->NodeAt(0), arguments->NodeAt(1));
}
return new (Z) StaticCallNode(ident_pos, func, arguments);
return new (Z)
StaticCallNode(ident_pos, func, arguments, StaticCallNode::kStatic);
}
AstNode* Parser::ParseInstanceCall(AstNode* receiver,
+23 -18
View File
@@ -443,41 +443,45 @@ ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind,
}
StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
const Function& function) const {
const Function& function,
ICData::RebindRule rebind_rule) const {
ZoneGrowableArray<PushArgumentInstr*>* arguments =
new (Z) ZoneGrowableArray<PushArgumentInstr*>(0);
return StaticCall(function, arguments);
}
StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
const Function& function,
PushArgumentInstr* arg1) const {
ZoneGrowableArray<PushArgumentInstr*>* arguments =
new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
arguments->Add(arg1);
return StaticCall(function, arguments);
return StaticCall(function, arguments, rebind_rule);
}
StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
const Function& function,
PushArgumentInstr* arg1,
PushArgumentInstr* arg2) const {
ICData::RebindRule rebind_rule) const {
ZoneGrowableArray<PushArgumentInstr*>* arguments =
new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
arguments->Add(arg1);
return StaticCall(function, arguments, rebind_rule);
}
StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
const Function& function,
PushArgumentInstr* arg1,
PushArgumentInstr* arg2,
ICData::RebindRule rebind_rule) const {
ZoneGrowableArray<PushArgumentInstr*>* arguments =
new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
arguments->Add(arg1);
arguments->Add(arg2);
return StaticCall(function, arguments);
return StaticCall(function, arguments, rebind_rule);
}
StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
const Function& function,
ZoneGrowableArray<PushArgumentInstr*>* arguments) const {
ZoneGrowableArray<PushArgumentInstr*>* arguments,
ICData::RebindRule rebind_rule) const {
const intptr_t kTypeArgsLen = 0;
return new (Z) StaticCallInstr(TokenPosition::kNoSource, function,
kTypeArgsLen, Object::null_array(), arguments,
ic_data_array_, GetNextDeoptId());
ic_data_array_, GetNextDeoptId(), rebind_rule);
}
InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
@@ -640,7 +644,7 @@ void IRRegExpMacroAssembler::Print(PushArgumentInstr* argument) {
const Library& lib = Library::Handle(Library::CoreLibrary());
const Function& print_fn =
Function::ZoneHandle(Z, lib.LookupFunctionAllowPrivate(Symbols::print()));
Do(StaticCall(print_fn, argument));
Do(StaticCall(print_fn, argument, ICData::kStatic));
}
void IRRegExpMacroAssembler::PrintBlocks() {
@@ -1469,7 +1473,8 @@ void IRRegExpMacroAssembler::GrowStack() {
const Library& lib = Library::Handle(Library::InternalLibrary());
const Function& grow_function = Function::ZoneHandle(
Z, lib.LookupFunctionAllowPrivate(Symbols::GrowRegExpStack()));
StoreLocal(stack_, Bind(StaticCall(grow_function, PushLocal(stack_))));
StoreLocal(stack_, Bind(StaticCall(grow_function, PushLocal(stack_),
ICData::kStatic)));
// Note: :stack and stack_array_cell content might diverge because each
// instance of :matcher code has its own stack_array_cell embedded into it
+9 -6
View File
@@ -243,15 +243,18 @@ class IRRegExpMacroAssembler : public RegExpMacroAssembler {
const InstanceCallDescriptor& desc,
ZoneGrowableArray<PushArgumentInstr*>* arguments) const;
StaticCallInstr* StaticCall(const Function& function) const;
StaticCallInstr* StaticCall(const Function& function,
PushArgumentInstr* arg1) const;
ICData::RebindRule rebind_rule) const;
StaticCallInstr* StaticCall(const Function& function,
PushArgumentInstr* arg1,
PushArgumentInstr* arg2) const;
StaticCallInstr* StaticCall(
const Function& function,
ZoneGrowableArray<PushArgumentInstr*>* arguments) const;
ICData::RebindRule rebind_rule) const;
StaticCallInstr* StaticCall(const Function& function,
PushArgumentInstr* arg1,
PushArgumentInstr* arg2,
ICData::RebindRule rebind_rule) const;
StaticCallInstr* StaticCall(const Function& function,
ZoneGrowableArray<PushArgumentInstr*>* arguments,
ICData::RebindRule rebind_rule) const;
// Creates a new block consisting simply of a goto to dst.
TargetEntryInstr* TargetWithJoinGoto(JoinEntryInstr* dst);
+3 -3
View File
@@ -1133,7 +1133,7 @@ DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 1) {
const ICData& ic_data =
ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
Thread::kNoDeoptId, 1, /* args_tested */
false /* static_call */));
ICData::kInstance));
// Maybe add the new target.
Class& cls = Class::Handle(zone, receiver.clazz());
@@ -1209,7 +1209,7 @@ DEFINE_RUNTIME_ENTRY(UnlinkedCall, 2) {
const ICData& ic_data =
ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
Thread::kNoDeoptId, 1, /* args_tested */
false /* static_call */));
ICData::kInstance));
Class& cls = Class::Handle(zone, receiver.clazz());
ArgumentsDescriptor args_desc(descriptor);
@@ -1289,7 +1289,7 @@ DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) {
const ICData& ic_data =
ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
Thread::kNoDeoptId, 1, /* args_tested */
false /* static_call */));
ICData::kInstance));
// Add the first target.
ic_data.AddReceiverCheck(old_expected_cid.Value(), old_target);