diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc index 82f82591d45..3e62efe5ba1 100644 --- a/runtime/vm/compiler/aot/aot_call_specializer.cc +++ b/runtime/vm/compiler/aot/aot_call_specializer.cc @@ -195,16 +195,9 @@ bool AotCallSpecializer::TryReplaceWithHaveSameRuntimeType( cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType())); ASSERT(!have_same_runtime_type.IsNull()); - ZoneGrowableArray* args = - new (Z) ZoneGrowableArray(2); - PushArgumentInstr* arg1 = - new (Z) PushArgumentInstr(new (Z) Value(left->ArgumentAt(0))); - InsertBefore(call, arg1, nullptr, FlowGraph::kEffect); - args->Add(arg1); - PushArgumentInstr* arg2 = - new (Z) PushArgumentInstr(new (Z) Value(right->ArgumentAt(0))); - InsertBefore(call, arg2, nullptr, FlowGraph::kEffect); - args->Add(arg2); + InputsArray* args = new (Z) InputsArray(Z, 2); + args->Add(left->ArgumentValueAt(0)->CopyWithType(Z)); + args->Add(right->ArgumentValueAt(0)->CopyWithType(Z)); const intptr_t kTypeArgsLen = 0; StaticCallInstr* static_call = new (Z) StaticCallInstr( call->token_pos(), have_same_runtime_type, kTypeArgsLen, @@ -212,7 +205,13 @@ bool AotCallSpecializer::TryReplaceWithHaveSameRuntimeType( args, call->deopt_id(), call->CallCount(), ICData::kOptimized); static_call->SetResultType(Z, CompileType::FromCid(kBoolCid)); ReplaceCall(call, static_call); - static_call->RepairPushArgsInEnvironment(); + // ReplaceCall moved environment from 'call' to 'static_call'. + // Update arguments of 'static_call' in the environment. + Environment* env = static_call->env(); + env->ValueAt(env->Length() - 2) + ->BindToEnvironment(static_call->ArgumentAt(0)); + env->ValueAt(env->Length() - 1) + ->BindToEnvironment(static_call->ArgumentAt(1)); return true; } @@ -389,18 +388,17 @@ bool AotCallSpecializer::TryOptimizeStaticCallUsingStaticTypes( cid == kDoubleCid) { // Sometimes TFA de-virtualizes instance calls to static calls. In such // cases the VM might have a looser type on the receiver, so we explicitly - // tighten it (this is safe since it was proven that te receiver is either + // tighten it (this is safe since it was proven that the receiver is either // null or will end up with that target). const intptr_t receiver_index = instr->FirstArgIndex(); const intptr_t argument_count = instr->ArgumentCountWithoutTypeArgs(); if (argument_count >= 1) { - auto push_receiver = instr->PushArgumentAt(receiver_index); - auto receiver_value = push_receiver->value(); + auto receiver_value = instr->ArgumentValueAt(receiver_index); auto receiver = receiver_value->definition(); auto type = BuildStrengthenedReceiverType(receiver_value, cid); if (!type.IsNone()) { - auto redefinition = flow_graph()->EnsureRedefinition( - push_receiver->previous(), receiver, type); + auto redefinition = + flow_graph()->EnsureRedefinition(instr->previous(), receiver, type); if (redefinition != nullptr) { RefineUseTypes(redefinition); } @@ -1116,9 +1114,8 @@ bool AotCallSpecializer::TryExpandCallThroughGetter(const Class& receiver_class, const intptr_t receiver_idx = call->type_args_len() > 0 ? 1 : 0; - PushArgumentsArray* get_arguments = new (Z) PushArgumentsArray(1); - get_arguments->Add(new (Z) PushArgumentInstr( - call->ArgumentValueAt(receiver_idx)->CopyWithType(Z))); + InputsArray* get_arguments = new (Z) InputsArray(Z, 1); + get_arguments->Add(call->ArgumentValueAt(receiver_idx)->CopyWithType(Z)); InstanceCallInstr* invoke_get = new (Z) InstanceCallInstr( call->token_pos(), getter_name, Token::kGET, get_arguments, /*type_args_len=*/0, @@ -1129,16 +1126,13 @@ bool AotCallSpecializer::TryExpandCallThroughGetter(const Class& receiver_class, // Arguments to the .call() are the same as arguments to the // original call (including type arguments), but receiver // is replaced with the result of the get. - PushArgumentsArray* call_arguments = - new (Z) PushArgumentsArray(call->ArgumentCount()); + InputsArray* call_arguments = new (Z) InputsArray(Z, call->ArgumentCount()); if (call->type_args_len() > 0) { - call_arguments->Add( - new (Z) PushArgumentInstr(call->ArgumentValueAt(0)->CopyWithType(Z))); + call_arguments->Add(call->ArgumentValueAt(0)->CopyWithType(Z)); } - call_arguments->Add(new (Z) PushArgumentInstr(new (Z) Value(invoke_get))); + call_arguments->Add(new (Z) Value(invoke_get)); for (intptr_t i = receiver_idx + 1; i < call->ArgumentCount(); i++) { - call_arguments->Add( - new (Z) PushArgumentInstr(call->ArgumentValueAt(i)->CopyWithType(Z))); + call_arguments->Add(call->ArgumentValueAt(i)->CopyWithType(Z)); } InstanceCallInstr* invoke_call = new (Z) InstanceCallInstr( @@ -1147,30 +1141,25 @@ bool AotCallSpecializer::TryExpandCallThroughGetter(const Class& receiver_class, /*checked_argument_count=*/1, thread()->compiler_state().GetNextDeoptId()); - // Insert all new instructions, except .call() invocation into the - // graph. + // Create environment and insert 'invoke_get'. Environment* get_env = call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount()); for (intptr_t i = 0, n = invoke_get->ArgumentCount(); i < n; i++) { - PushArgumentInstr* push = invoke_get->PushArgumentAt(i); - InsertBefore(call, push, nullptr, FlowGraph::kEffect); - get_env->PushValue(new (Z) Value(push)); // add PushArg to getter's env + get_env->PushValue(new (Z) Value(invoke_get->ArgumentAt(i))); } InsertBefore(call, invoke_get, get_env, FlowGraph::kValue); - for (intptr_t i = 0, n = invoke_call->ArgumentCount(); i < n; i++) { - InsertBefore(call, invoke_call->PushArgumentAt(i), nullptr, - FlowGraph::kEffect); - } - // Replace original PushArguments in the graph (mainly env uses). - ASSERT(call->ArgumentCount() == invoke_call->ArgumentCount()); - for (intptr_t i = 0, n = call->ArgumentCount(); i < n; i++) { - call->PushArgumentAt(i)->ReplaceUsesWith(invoke_call->PushArgumentAt(i)); - call->PushArgumentAt(i)->RemoveFromGraph(); - } // Replace original call with .call(...) invocation. call->ReplaceWith(invoke_call, current_iterator()); + // ReplaceWith moved environment from 'call' to 'invoke_call'. + // Update receiver argument in the environment. + Environment* invoke_env = invoke_call->env(); + invoke_env + ->ValueAt(invoke_env->Length() - invoke_call->ArgumentCount() + + receiver_idx) + ->BindToEnvironment(invoke_get); + // AOT compiler expects all calls to have an ICData. EnsureICData(Z, flow_graph()->function(), invoke_get); EnsureICData(Z, flow_graph()->function(), invoke_call); @@ -1243,17 +1232,10 @@ bool AotCallSpecializer::TryReplaceInstanceOfWithRangeCheck( ConstantInstr* upper_cid = flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(upper_limit))); - ZoneGrowableArray* args = - new (Z) ZoneGrowableArray(3); - PushArgumentInstr* arg = new (Z) PushArgumentInstr(new (Z) Value(left_cid)); - InsertBefore(call, arg, NULL, FlowGraph::kEffect); - args->Add(arg); - arg = new (Z) PushArgumentInstr(new (Z) Value(lower_cid)); - InsertBefore(call, arg, NULL, FlowGraph::kEffect); - args->Add(arg); - arg = new (Z) PushArgumentInstr(new (Z) Value(upper_cid)); - InsertBefore(call, arg, NULL, FlowGraph::kEffect); - args->Add(arg); + InputsArray* args = new (Z) InputsArray(Z, 3); + args->Add(new (Z) Value(left_cid)); + args->Add(new (Z) Value(lower_cid)); + args->Add(new (Z) Value(upper_cid)); const Library& dart_internal = Library::Handle(Z, Library::InternalLibrary()); const String& target_name = Symbols::_classRangeCheck(); @@ -1271,7 +1253,7 @@ bool AotCallSpecializer::TryReplaceInstanceOfWithRangeCheck( Environment* copy = call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount()); for (intptr_t i = 0; i < args->length(); ++i) { - copy->PushValue(new (Z) Value((*args)[i])); // add PushArg to env + copy->PushValue(new (Z) Value(new_call->ArgumentAt(i))); } call->RemoveEnvironment(); ReplaceCall(call, new_call); diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc index cf618d83d29..3592d567733 100644 --- a/runtime/vm/compiler/backend/constant_propagator.cc +++ b/runtime/vm/compiler/backend/constant_propagator.cc @@ -379,22 +379,7 @@ void ConstantPropagator::VisitNativeParameter(NativeParameterInstr* instr) { } void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) { - if (SetValue(instr, instr->value()->definition()->constant_value())) { - // The worklist implementation breaks down around push arguments, - // since these instructions do not have a direct use-link to the - // corresponding call. This is remedied by visiting all calls in - // the enviroment use list each time a push argument changes its - // value. Currently, this only needs to be done for static calls - // (the only calls involved in constant propagation). - // TODO(ajcbik): calls with multiple arguments may be revisited - // several times; a direct use-link would be better - for (Value* use = instr->env_use_list(); use != nullptr; - use = use->next_use()) { - if (use->instruction()->IsStaticCall()) { - use->instruction()->Accept(this); - } - } - } + UNREACHABLE(); } void ConstantPropagator::VisitAssertAssignable(AssertAssignableInstr* instr) { @@ -1438,15 +1423,6 @@ void ConstantPropagator::EliminateRedundantBranches() { } } -static void RemovePushArguments(StaticCallInstr* call) { - for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { - PushArgumentInstr* push = call->PushArgumentAt(i); - ASSERT(push->input_use_list() == nullptr); // no direct uses - push->ReplaceUsesWith(push->value()->definition()); // cleanup env uses - push->RemoveFromGraph(); - } -} - void ConstantPropagator::Transform() { // We will recompute dominators, block ordering, block ids, block last // instructions, previous pointers, predecessors, etc. after eliminating @@ -1521,11 +1497,11 @@ void ConstantPropagator::Transform() { // Replace constant-valued instructions without observable side // effects. Do this for smis only to avoid having to copy other // objects into the heap's old generation. - if ((defn != NULL) && IsConstant(defn->constant_value()) && + ASSERT((defn == nullptr) || !defn->IsPushArgument()); + if ((defn != nullptr) && IsConstant(defn->constant_value()) && (defn->constant_value().IsSmi() || defn->constant_value().IsOld()) && - !defn->IsConstant() && !defn->IsPushArgument() && - !defn->IsStoreIndexed() && !defn->IsStoreInstanceField() && - !defn->IsStoreStaticField()) { + !defn->IsConstant() && !defn->IsStoreIndexed() && + !defn->IsStoreInstanceField() && !defn->IsStoreStaticField()) { if (FLAG_trace_constant_propagation && graph_->should_print()) { THR_Print("Constant v%" Pd " = %s\n", defn->ssa_temp_index(), defn->constant_value().ToCString()); @@ -1538,7 +1514,7 @@ void ConstantPropagator::Transform() { ASSERT(!value.IsNull() && (error_str == nullptr)); } if (auto call = defn->AsStaticCall()) { - RemovePushArguments(call); + ASSERT(!call->HasPushArguments()); } ConstantInstr* constant = graph_->GetConstant(value); defn->ReplaceUsesWith(constant); diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc index 9f49f446e87..ef9fa480c9f 100644 --- a/runtime/vm/compiler/backend/flow_graph.cc +++ b/runtime/vm/compiler/backend/flow_graph.cc @@ -90,16 +90,7 @@ void FlowGraph::ReplaceCurrentInstruction(ForwardInstructionIterator* iterator, } } if (current->ArgumentCount() != 0) { - // Replacing a call instruction with something else. Must remove - // superfluous push arguments. - for (intptr_t i = 0; i < current->ArgumentCount(); ++i) { - PushArgumentInstr* push = current->PushArgumentAt(i); - if (replacement == NULL || i >= replacement->ArgumentCount() || - replacement->PushArgumentAt(i) != push) { - push->ReplaceUsesWith(push->value()->definition()); - push->RemoveFromGraph(); - } - } + ASSERT(!current->HasPushArguments()); } iterator->RemoveCurrentFromGraph(); } @@ -1156,8 +1147,10 @@ void FlowGraph::AttachEnvironment(Instruction* instr, Environment* deopt_env = Environment::From(zone(), *env, num_direct_parameters_, parsed_function_); if (instr->IsClosureCall()) { + // Trim extra input of ClosureCall instruction. deopt_env = - deopt_env->DeepCopy(zone(), deopt_env->Length() - instr->InputCount()); + deopt_env->DeepCopy(zone(), deopt_env->Length() - instr->InputCount() + + instr->ArgumentCount()); } instr->SetEnvironment(deopt_env); for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) { @@ -1249,7 +1242,9 @@ void FlowGraph::RenameRecursive( // generate the constant rather than going through a synthetic phi. if (input_defn->IsConstant() && reaching_defn->IsPhi()) { ASSERT(env->length() < osr_variable_count()); - reaching_defn = GetConstant(input_defn->AsConstant()->value()); + auto constant = GetConstant(input_defn->AsConstant()->value()); + current->ReplaceInEnvironment(reaching_defn, constant); + reaching_defn = constant; } } else { // Note: constants can only be replaced with other constants. @@ -1266,52 +1261,8 @@ void FlowGraph::RenameRecursive( input_defn->AddInputUse(v); } - // 2b. Handle arguments. Usually this just consists of popping - // all consumed parameters from the expression stack. However, - // during OSR with a non-empty stack, PushArguments may have - // been lost (since the defining value resides in the now - // removed original entry). - Instruction* insert_at = current; // keeps push arguments in order - for (intptr_t i = current->ArgumentCount() - 1; i >= 0; --i) { - // Update expression stack. - ASSERT(env->length() > variable_count()); - Definition* reaching_defn = env->RemoveLast(); - if (reaching_defn->IsPushArgument()) { - insert_at = reaching_defn; - } else { - // We lost the PushArgument! This situation can only happen - // during OSR with a non-empty stack: replace the argument - // with the incoming parameter that mimics the stack slot. - ASSERT(IsCompiledForOsr()); - PushArgumentInstr* push_arg = current->PushArgumentAt(i); - ASSERT(reaching_defn->ssa_temp_index() != -1); - ASSERT(reaching_defn->IsPhi() || reaching_defn == constant_dead()); - push_arg->ReplaceUsesWith(push_arg->InputAt(0)->definition()); - push_arg->UnuseAllInputs(); - push_arg->previous()->LinkTo(push_arg->next()); - push_arg->set_previous(nullptr); - push_arg->set_next(nullptr); - push_arg->value()->set_definition(reaching_defn); - InsertBefore(insert_at, push_arg, nullptr, FlowGraph::kEffect); - insert_at = push_arg; - // Since reaching_defn was not the expected PushArgument, we must - // change all its environment uses from the insertion point onward - // to the newly created PushArgument. This ensures that the stack - // depth computations (based on environment presence of PushArguments) - // is done correctly. - for (Value::Iterator it(reaching_defn->env_use_list()); !it.Done(); - it.Advance()) { - Instruction* instruction = it.Current()->instruction(); - if (instruction->IsDominatedBy(push_arg)) { - instruction->ReplaceInEnvironment(reaching_defn, push_arg); - } - } - } - } - - // 2c. Handle LoadLocal/StoreLocal/MakeTemp/DropTemps/Constant and - // PushArgument specially. Other definitions are just pushed - // to the environment directly. + // 2b. Handle LoadLocal/StoreLocal/MakeTemp/DropTemps/Constant specially. + // Other definitions are just pushed to the environment directly. Definition* result = NULL; switch (current->tag()) { case Instruction::kLoadLocal: { @@ -1400,8 +1351,8 @@ void FlowGraph::RenameRecursive( } case Instruction::kPushArgument: - env->Add(current->Cast()); - continue; + UNREACHABLE(); + break; case Instruction::kCheckStackOverflow: // Assert environment integrity at checkpoints. @@ -1469,12 +1420,7 @@ void FlowGraph::RenameRecursive( // Rename input operand. Definition* input = (*env)[i]; ASSERT(input != nullptr); - if (input->IsPushArgument()) { - // A push argument left on expression stack - // requires the variable name in SSA phis. - ASSERT(IsCompiledForOsr()); - input = input->InputAt(0)->definition(); - } + ASSERT(!input->IsPushArgument()); Value* use = new (zone()) Value(input); phi->SetInputAt(pred_index, use); } @@ -2078,7 +2024,9 @@ void FlowGraph::WidenSmiToInt32() { if (use_defn == NULL) { // We assume that tagging before returning or pushing argument costs // very little compared to the cost of the return/call itself. - if (!instr->IsReturn() && !instr->IsPushArgument()) { + ASSERT(!instr->IsPushArgument()); + if (!instr->IsReturn() && + (use->use_index() >= instr->ArgumentCount())) { gain--; if (FLAG_support_il_printer && FLAG_trace_smi_widening) { THR_Print("v [%" Pd "] (u) %s\n", gain, @@ -2618,6 +2566,37 @@ PhiInstr* FlowGraph::AddPhi(JoinEntryInstr* join, return phi; } +void FlowGraph::InsertPushArguments() { + for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done(); + block_it.Advance()) { + thread()->CheckForSafepoint(); + for (ForwardInstructionIterator instr_it(block_it.Current()); + !instr_it.Done(); instr_it.Advance()) { + Instruction* instruction = instr_it.Current(); + const intptr_t arg_count = instruction->ArgumentCount(); + if (arg_count == 0) { + continue; + } + PushArgumentsArray* arguments = + new (Z) PushArgumentsArray(zone(), arg_count); + for (intptr_t i = 0; i < arg_count; ++i) { + Value* arg = instruction->ArgumentValueAt(i); + PushArgumentInstr* push_arg = + new (Z) PushArgumentInstr(arg->CopyWithType(Z)); + arguments->Add(push_arg); + // Insert all PushArgument instructions immediately before call. + // PushArgumentInstr::EmitNativeCode may generate more efficient + // code for subsequent PushArgument instructions (ARM, ARM64). + InsertBefore(instruction, push_arg, /*env=*/nullptr, kEffect); + } + instruction->ReplaceInputsWithPushArguments(arguments); + if (instruction->env() != nullptr) { + instruction->RepairPushArgsInEnvironment(); + } + } + } +} + } // namespace dart #endif // !defined(DART_PRECOMPILED_RUNTIME) diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h index 3622a5c4fbe..b6ff5310f72 100644 --- a/runtime/vm/compiler/backend/flow_graph.h +++ b/runtime/vm/compiler/backend/flow_graph.h @@ -289,6 +289,10 @@ class FlowGraph : public ZoneAllocated { // Remove the redefinition instructions inserted to inhibit code motion. void RemoveRedefinitions(bool keep_checks = false); + // Insert PushArgument instructions and remove explicit def-use + // relations between calls and their arguments. + void InsertPushArguments(); + // Copy deoptimization target from one instruction to another if we still // have to keep deoptimization environment at gotos for LICM purposes. void CopyDeoptTarget(Instruction* to, Instruction* from) { diff --git a/runtime/vm/compiler/backend/flow_graph_checker.cc b/runtime/vm/compiler/backend/flow_graph_checker.cc index c861c5d3cf9..5d7c523d3c2 100644 --- a/runtime/vm/compiler/backend/flow_graph_checker.cc +++ b/runtime/vm/compiler/backend/flow_graph_checker.cc @@ -106,8 +106,8 @@ static bool IsControlFlow(Instruction* instruction) { instruction->IsStop() || instruction->IsTailCall(); } -// Asserts push arguments appear in environment at the right place. -static void AssertPushArgsInEnv(FlowGraph* flow_graph, Definition* call) { +// Asserts that arguments appear in environment at the right place. +static void AssertArgumentsInEnv(FlowGraph* flow_graph, Definition* call) { Environment* env = call->env(); if (env == nullptr) { // Environments can be removed by EliminateEnvironments pass and @@ -116,14 +116,35 @@ static void AssertPushArgsInEnv(FlowGraph* flow_graph, Definition* call) { // TODO(dartbug.com/38577): cleanup regexp pipeline too.... } else { // Otherwise, the trailing environment entries must - // correspond directly with the PushArguments. + // correspond directly with the arguments. const intptr_t env_count = env->Length(); const intptr_t arg_count = call->ArgumentCount(); ASSERT(arg_count <= env_count); const intptr_t env_base = env_count - arg_count; for (intptr_t i = 0; i < arg_count; i++) { - ASSERT(call->PushArgumentAt(i) == - env->ValueAt(env_base + i)->definition()); + if (call->HasPushArguments()) { + ASSERT(call->ArgumentAt(i) == env->ValueAt(env_base + i) + ->definition() + ->AsPushArgument() + ->value() + ->definition()); + } else { + // Redefintion instructions and boxing/unboxing are inserted + // without updating environment uses (FlowGraph::RenameDominatedUses, + // FlowGraph::InsertConversionsFor). + // Also, constants may belong to different blocks (e.g. function entry + // and graph entry). + Definition* arg_def = + call->ArgumentAt(i)->OriginalDefinitionIgnoreBoxingAndConstraints(); + Definition* env_def = + env->ValueAt(env_base + i) + ->definition() + ->OriginalDefinitionIgnoreBoxingAndConstraints(); + ASSERT((arg_def == env_def) || + (arg_def->IsConstant() && env_def->IsConstant() && + arg_def->AsConstant()->value().raw() == + env_def->AsConstant()->value().raw())); + } } } } @@ -419,15 +440,15 @@ void FlowGraphChecker::VisitRedefinition(RedefinitionInstr* def) { } void FlowGraphChecker::VisitClosureCall(ClosureCallInstr* call) { - AssertPushArgsInEnv(flow_graph_, call); + AssertArgumentsInEnv(flow_graph_, call); } void FlowGraphChecker::VisitStaticCall(StaticCallInstr* call) { - AssertPushArgsInEnv(flow_graph_, call); + AssertArgumentsInEnv(flow_graph_, call); } void FlowGraphChecker::VisitInstanceCall(InstanceCallInstr* call) { - AssertPushArgsInEnv(flow_graph_, call); + AssertArgumentsInEnv(flow_graph_, call); // Force-optimized functions may not have instance calls inside them because // we do not reset ICData for these. ASSERT(!flow_graph_->function().ForceOptimize()); @@ -435,7 +456,7 @@ void FlowGraphChecker::VisitInstanceCall(InstanceCallInstr* call) { void FlowGraphChecker::VisitPolymorphicInstanceCall( PolymorphicInstanceCallInstr* call) { - AssertPushArgsInEnv(flow_graph_, call); + AssertArgumentsInEnv(flow_graph_, call); // Force-optimized functions may not have instance calls inside them because // we do not reset ICData for these. ASSERT(!flow_graph_->function().ForceOptimize()); diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index 88e6c49196c..6bdb4d399fd 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -534,7 +534,8 @@ Definition* Definition::OriginalDefinitionIgnoreBoxingAndConstraints() { Definition* def = this; while (true) { Definition* orig; - if (def->IsConstraint() || def->IsBox() || def->IsUnbox()) { + if (def->IsConstraint() || def->IsBox() || def->IsUnbox() || + def->IsIntConverter()) { orig = def->InputAt(0)->definition(); } else { orig = def->OriginalDefinition(); @@ -1484,11 +1485,13 @@ void Instruction::UnuseAllInputs() { } void Instruction::RepairPushArgsInEnvironment() const { + PushArgumentsArray* push_arguments = GetPushArguments(); + ASSERT(push_arguments != nullptr); const intptr_t arg_count = ArgumentCount(); ASSERT(arg_count <= env()->Length()); const intptr_t env_base = env()->Length() - arg_count; for (intptr_t i = 0; i < arg_count; ++i) { - env()->ValueAt(env_base + i)->BindToEnvironment(PushArgumentAt(i)); + env()->ValueAt(env_base + i)->BindToEnvironment(push_arguments->At(i)); } } @@ -4459,6 +4462,12 @@ intptr_t PolymorphicInstanceCallInstr::CallCount() const { return targets().AggregateCallCount(); } +LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( + Zone* zone, + bool optimizing) const { + return MakeCallSummary(zone); +} + void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { ArgumentsInfo args_info(type_args_len(), ArgumentCount(), argument_names()); compiler->EmitPolymorphicInstanceCall(targets_, *instance_call(), args_info, @@ -5335,6 +5344,11 @@ intptr_t TruncDivModInstr::OutputIndexOf(Token::Kind token) { } } +LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, + bool optimizing) const { + return MakeCallSummary(zone); +} + void NativeCallInstr::SetupNative() { if (link_lazily()) { // Resolution will happen during NativeEntry::LinkNativeCall. diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h index 3e1ad4cc5f3..9d4e713a699 100644 --- a/runtime/vm/compiler/backend/il.h +++ b/runtime/vm/compiler/backend/il.h @@ -751,6 +751,9 @@ class BinaryFeedback : public ZoneAllocated { friend class Cids; }; +typedef ZoneGrowableArray InputsArray; +typedef ZoneGrowableArray PushArgumentsArray; + class Instruction : public ZoneAllocated { public: #define DECLARE_TAG(type, attrs) k##type, @@ -809,13 +812,25 @@ class Instruction : public ZoneAllocated { // Call instructions override this function and return the number of // pushed arguments. virtual intptr_t ArgumentCount() const { return 0; } - virtual PushArgumentInstr* PushArgumentAt(intptr_t index) const { - UNREACHABLE(); - return NULL; - } inline Value* ArgumentValueAt(intptr_t index) const; inline Definition* ArgumentAt(intptr_t index) const; + // Sets array of PushArgument instructions. + virtual void SetPushArguments(PushArgumentsArray* push_arguments) { + UNREACHABLE(); + } + // Returns array of PushArgument instructions + virtual PushArgumentsArray* GetPushArguments() const { + UNREACHABLE(); + return nullptr; + } + // Replace inputs with separate PushArgument instructions detached from call. + virtual void ReplaceInputsWithPushArguments( + PushArgumentsArray* push_arguments) { + UNREACHABLE(); + } + bool HasPushArguments() const { return GetPushArguments() != nullptr; } + // Repairs trailing PushArgs in environment. void RepairPushArgsInEnvironment() const; @@ -2686,7 +2701,9 @@ class PushArgumentInstr : public TemplateDefinition<1, NoThrow> { }; inline Value* Instruction::ArgumentValueAt(intptr_t index) const { - return PushArgumentAt(index)->value(); + PushArgumentsArray* push_arguments = GetPushArguments(); + return push_arguments != nullptr ? (*push_arguments)[index]->value() + : InputAt(index); } inline Definition* Instruction::ArgumentAt(intptr_t index) const { @@ -2772,8 +2789,6 @@ class NativeReturnInstr : public ReturnInstr { DISALLOW_COPY_AND_ASSIGN(NativeReturnInstr); }; -typedef ZoneGrowableArray PushArgumentsArray; - class ThrowInstr : public TemplateInstruction<1, Throws> { public: explicit ThrowInstr(TokenPosition token_pos, @@ -3088,8 +3103,11 @@ class BranchInstr : public Instruction { virtual intptr_t ArgumentCount() const { return comparison()->ArgumentCount(); } - virtual PushArgumentInstr* PushArgumentAt(intptr_t index) const { - return comparison()->PushArgumentAt(index); + virtual void SetPushArguments(PushArgumentsArray* push_arguments) { + comparison()->SetPushArguments(push_arguments); + } + virtual PushArgumentsArray* GetPushArguments() const { + return comparison()->GetPushArguments(); } intptr_t InputCount() const { return comparison()->InputCount(); } @@ -3561,20 +3579,24 @@ struct ArgumentsInfo { const Array& argument_names; }; -template -class TemplateDartCall : public TemplateDefinition { +template +class TemplateDartCall : public Definition { public: TemplateDartCall(intptr_t deopt_id, intptr_t type_args_len, const Array& argument_names, - PushArgumentsArray* arguments, + InputsArray* inputs, TokenPosition token_pos) - : TemplateDefinition(deopt_id), + : Definition(deopt_id), type_args_len_(type_args_len), argument_names_(argument_names), - arguments_(arguments), + inputs_(inputs), token_pos_(token_pos) { ASSERT(argument_names.IsZoneHandle() || argument_names.InVMIsolateHeap()); + ASSERT(inputs_->length() >= kExtraInputs); + for (intptr_t i = 0, n = inputs_->length(); i < n; ++i) { + SetInputAt(i, (*inputs_)[i]); + } } RawString* Selector() { @@ -3587,16 +3609,43 @@ class TemplateDartCall : public TemplateDefinition { } } + virtual bool MayThrow() const { return true; } + + virtual intptr_t InputCount() const { return inputs_->length(); } + virtual Value* InputAt(intptr_t i) const { return inputs_->At(i); } + intptr_t FirstArgIndex() const { return type_args_len_ > 0 ? 1 : 0; } Value* Receiver() const { return this->ArgumentValueAt(FirstArgIndex()); } intptr_t ArgumentCountWithoutTypeArgs() const { - return arguments_->length() - FirstArgIndex(); + return ArgumentCount() - FirstArgIndex(); } // ArgumentCount() includes the type argument vector if any. // Caution: Must override Instruction::ArgumentCount(). - virtual intptr_t ArgumentCount() const { return arguments_->length(); } - virtual PushArgumentInstr* PushArgumentAt(intptr_t index) const { - return (*arguments_)[index]; + virtual intptr_t ArgumentCount() const { + return push_arguments_ != nullptr ? push_arguments_->length() + : inputs_->length() - kExtraInputs; + } + virtual void SetPushArguments(PushArgumentsArray* push_arguments) { + ASSERT(push_arguments_ == nullptr); + push_arguments_ = push_arguments; + } + virtual PushArgumentsArray* GetPushArguments() const { + return push_arguments_; + } + virtual void ReplaceInputsWithPushArguments( + PushArgumentsArray* push_arguments) { + ASSERT(push_arguments_ == nullptr); + ASSERT(push_arguments->length() == ArgumentCount()); + SetPushArguments(push_arguments); + ASSERT(inputs_->length() == ArgumentCount() + kExtraInputs); + const intptr_t extra_inputs_base = inputs_->length() - kExtraInputs; + for (intptr_t i = 0, n = ArgumentCount(); i < n; ++i) { + InputAt(i)->RemoveFromUseList(); + } + for (intptr_t i = 0; i < kExtraInputs; ++i) { + SetInputAt(i, InputAt(extra_inputs_base + i)); + } + inputs_->TruncateTo(kExtraInputs); } intptr_t type_args_len() const { return type_args_len_; } const Array& argument_names() const { return argument_names_; } @@ -3609,9 +3658,14 @@ class TemplateDartCall : public TemplateDefinition { ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT private: + virtual void RawSetInputAt(intptr_t i, Value* value) { + (*inputs_)[i] = value; + } + intptr_t type_args_len_; const Array& argument_names_; - PushArgumentsArray* arguments_; + InputsArray* inputs_; + PushArgumentsArray* push_arguments_ = nullptr; TokenPosition token_pos_; DISALLOW_COPY_AND_ASSIGN(TemplateDartCall); @@ -3619,8 +3673,7 @@ class TemplateDartCall : public TemplateDefinition { class ClosureCallInstr : public TemplateDartCall<1> { public: - ClosureCallInstr(Value* function, - PushArgumentsArray* arguments, + ClosureCallInstr(InputsArray* inputs, intptr_t type_args_len, const Array& argument_names, TokenPosition token_pos, @@ -3629,12 +3682,9 @@ class ClosureCallInstr : public TemplateDartCall<1> { : TemplateDartCall(deopt_id, type_args_len, argument_names, - arguments, + inputs, token_pos), - entry_kind_(entry_kind) { - ASSERT(!arguments->is_empty()); - SetInputAt(0, function); - } + entry_kind_(entry_kind) {} DECLARE_INSTRUCTION(ClosureCall) @@ -3662,7 +3712,7 @@ class InstanceCallInstr : public TemplateDartCall<0> { TokenPosition token_pos, const String& function_name, Token::Kind token_kind, - PushArgumentsArray* arguments, + InputsArray* arguments, intptr_t type_args_len, const Array& argument_names, intptr_t checked_argument_count, @@ -3699,7 +3749,7 @@ class InstanceCallInstr : public TemplateDartCall<0> { TokenPosition token_pos, const String& function_name, Token::Kind token_kind, - PushArgumentsArray* arguments, + InputsArray* arguments, intptr_t type_args_len, const Array& argument_names, intptr_t checked_argument_count, @@ -3896,7 +3946,7 @@ class PolymorphicInstanceCallInstr : public TemplateDartCall<0> { private: PolymorphicInstanceCallInstr(InstanceCallInstr* instance_call, - PushArgumentsArray* arguments, + InputsArray* arguments, const CallTargets& targets, bool complete) : TemplateDartCall<0>(instance_call->deopt_id(), @@ -3918,10 +3968,11 @@ class PolymorphicInstanceCallInstr : public TemplateDartCall<0> { InstanceCallInstr* call_for_attributes, const CallTargets& targets, bool complete) { - PushArgumentsArray* args = new (zone) - PushArgumentsArray(zone, call_for_arguments->ArgumentCount()); + ASSERT(!call_for_arguments->HasPushArguments()); + InputsArray* args = + new (zone) InputsArray(zone, call_for_arguments->ArgumentCount()); for (intptr_t i = 0, n = call_for_arguments->ArgumentCount(); i < n; ++i) { - args->Add(call_for_arguments->PushArgumentAt(i)); + args->Add(call_for_arguments->ArgumentValueAt(i)->CopyWithType(zone)); } return new (zone) PolymorphicInstanceCallInstr(call_for_attributes, args, targets, complete); @@ -4232,7 +4283,7 @@ class StaticCallInstr : public TemplateDartCall<0> { const Function& function, intptr_t type_args_len, const Array& argument_names, - PushArgumentsArray* arguments, + InputsArray* arguments, const ZoneGrowableArray& ic_data_array, intptr_t deopt_id, ICData::RebindRule rebind_rule) @@ -4257,7 +4308,7 @@ class StaticCallInstr : public TemplateDartCall<0> { const Function& function, intptr_t type_args_len, const Array& argument_names, - PushArgumentsArray* arguments, + InputsArray* arguments, intptr_t deopt_id, intptr_t call_count, ICData::RebindRule rebind_rule) @@ -4284,10 +4335,10 @@ class StaticCallInstr : public TemplateDartCall<0> { const C* call, const Function& target, intptr_t call_count) { - PushArgumentsArray* args = - new (zone) PushArgumentsArray(call->ArgumentCount()); + ASSERT(!call->HasPushArguments()); + InputsArray* args = new (zone) InputsArray(zone, call->ArgumentCount()); for (intptr_t i = 0; i < call->ArgumentCount(); i++) { - args->Add(call->PushArgumentAt(i)); + args->Add(call->ArgumentValueAt(i)->CopyWithType()); } StaticCallInstr* new_call = new (zone) StaticCallInstr(call->token_pos(), target, call->type_args_len(), @@ -4296,6 +4347,9 @@ class StaticCallInstr : public TemplateDartCall<0> { if (call->result_type() != NULL) { new_call->result_type_ = call->result_type(); } + if (call->has_inlining_id()) { + new_call->set_inlining_id(call->inlining_id()); + } new_call->set_entry_kind(call->entry_kind()); return new_call; } @@ -4553,7 +4607,7 @@ class NativeCallInstr : public TemplateDartCall<0> { const Function* function, bool link_lazily, TokenPosition position, - PushArgumentsArray* args) + InputsArray* args) : TemplateDartCall(DeoptId::kNone, 0, Array::null_array(), diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index c2349e7faa0..b0efd4ef6dd 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -85,21 +85,133 @@ LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, return locs; } +// Buffers registers to use STMDB in order to push +// multiple registers at once. +class ArgumentsPusher : public ValueObject { + public: + ArgumentsPusher() {} + + // Flush all buffered registers. + void Flush(FlowGraphCompiler* compiler) { + if (pending_regs_ != 0) { + if (is_single_register_) { + __ Push(lowest_register_); + } else { + __ PushList(pending_regs_); + } + pending_regs_ = 0; + lowest_register_ = kNoRegister; + is_single_register_ = false; + } + } + + // Buffer given register. May push previously buffered registers if needed. + void PushRegister(FlowGraphCompiler* compiler, Register reg) { + if (pending_regs_ != 0) { + ASSERT(lowest_register_ != kNoRegister); + // STMDB pushes higher registers first, so we can only buffer + // lower registers. + if (reg < lowest_register_) { + pending_regs_ |= (1 << reg); + lowest_register_ = reg; + is_single_register_ = false; + return; + } + Flush(compiler); + } + pending_regs_ = (1 << reg); + lowest_register_ = reg; + is_single_register_ = true; + } + + // Return a register which can be used to hold a value of an argument. + Register FindFreeRegister(FlowGraphCompiler* compiler, + Instruction* push_arg) { + // Dart calling conventions do not have callee-save registers, + // so arguments pushing can clobber all allocatable registers + // except registers used in arguments which were not pushed yet, + // as well as ParallelMove and inputs of a call instruction. + intptr_t busy = kReservedCpuRegisters; + for (Instruction* instr = push_arg;; instr = instr->next()) { + ASSERT(instr != nullptr); + if (ParallelMoveInstr* parallel_move = instr->AsParallelMove()) { + for (intptr_t i = 0, n = parallel_move->NumMoves(); i < n; ++i) { + if (parallel_move->MoveOperandsAt(i)->src().IsRegister()) { + busy |= (1 << parallel_move->MoveOperandsAt(i)->src().reg()); + } + } + } else { + ASSERT(instr->IsPushArgument() || (instr->ArgumentCount() > 0)); + for (intptr_t i = 0, n = instr->locs()->input_count(); i < n; ++i) { + if (instr->locs()->in(i).IsRegister()) { + busy |= (1 << instr->locs()->in(i).reg()); + } + } + if (instr->ArgumentCount() > 0) { + break; + } + } + } + if (pending_regs_ != 0) { + // Find the highest available register which can be pushed along with + // pending registers. + Register reg = HighestAvailableRegister(busy, lowest_register_); + if (reg != kNoRegister) { + return reg; + } + Flush(compiler); + } + // At this point there are no pending buffered registers. + // Use LR as it's the highest free register, it is not allocatable and + // it is clobbered by the call. + static_assert(((1 << LR) & kDartAvailableCpuRegs) == 0, + "LR should not be allocatable"); + return LR; + } + + private: + RegList pending_regs_ = 0; + Register lowest_register_ = kNoRegister; + bool is_single_register_ = false; + + Register HighestAvailableRegister(intptr_t busy, Register upper_bound) { + for (intptr_t i = upper_bound - 1; i >= 0; --i) { + if ((busy & (1 << i)) == 0) { + return static_cast(i); + } + } + return kNoRegister; + } +}; + void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode - // where PushArgument is handled by BindInstr::EmitNativeCode. + // where arguments are pushed by their definitions. if (compiler->is_optimizing()) { - Location value = locs()->in(0); - if (value.IsRegister()) { - __ Push(value.reg()); - } else if (value.IsConstant()) { - __ PushObject(value.constant()); - } else { - ASSERT(value.IsStackSlot()); - const intptr_t value_offset = value.ToStackSlotOffset(); - __ LoadFromOffset(kWord, IP, value.base_reg(), value_offset); - __ Push(IP); + if (previous()->IsPushArgument()) { + // Already generated. + return; } + ArgumentsPusher pusher; + for (PushArgumentInstr* push_arg = this; push_arg != nullptr; + push_arg = push_arg->next()->AsPushArgument()) { + const Location value = push_arg->locs()->in(0); + if (value.IsRegister()) { + pusher.PushRegister(compiler, value.reg()); + } else { + const Register reg = pusher.FindFreeRegister(compiler, push_arg); + ASSERT(reg != kNoRegister); + if (value.IsConstant()) { + __ LoadObject(reg, value.constant()); + } else { + ASSERT(value.IsStackSlot()); + const intptr_t value_offset = value.ToStackSlotOffset(); + __ LoadFromOffset(kWord, reg, value.base_reg(), value_offset); + } + pusher.PushRegister(compiler, reg); + } + } + pusher.Flush(compiler); } } @@ -934,11 +1046,6 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, } } -LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, - bool opt) const { - return MakeCallSummary(zone); -} - void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { SetupNative(); const Register result = locs()->out(0).reg(); @@ -6107,12 +6214,6 @@ void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ Bind(&done); } -LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - return MakeCallSummary(zone); -} - LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { comparison()->InitializeLocationSummary(zone, opt); // Branches don't produce a result. diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index 9de63c379d1..2f5a6e99c5c 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -83,21 +83,76 @@ LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, return locs; } +// Buffers registers in order to use STP to push +// two registers at once. +class ArgumentsPusher : public ValueObject { + public: + ArgumentsPusher() {} + + // Flush all buffered registers. + void Flush(FlowGraphCompiler* compiler) { + if (pending_register_ != kNoRegister) { + __ Push(pending_register_); + pending_register_ = kNoRegister; + } + } + + // Buffer given register. May push buffered registers if needed. + void PushRegister(FlowGraphCompiler* compiler, Register reg) { + if (pending_register_ != kNoRegister) { + __ PushPair(reg, pending_register_); + pending_register_ = kNoRegister; + return; + } + pending_register_ = reg; + } + + // Returns free temp register to hold argument value. + Register GetFreeTempRegister() { + // While pushing arguments only Push, PushPair, LoadObject and + // LoadFromOffset are used. They do not clobber TMP or LR. + static_assert(((1 << LR) & kDartAvailableCpuRegs) == 0, + "LR should not be allocatable"); + static_assert(((1 << TMP) & kDartAvailableCpuRegs) == 0, + "TMP should not be allocatable"); + return (pending_register_ == TMP) ? LR : TMP; + } + + private: + Register pending_register_ = kNoRegister; +}; + void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode - // where PushArgument is handled by BindInstr::EmitNativeCode. + // where arguments are pushed by their definitions. if (compiler->is_optimizing()) { - Location value = locs()->in(0); - if (value.IsRegister()) { - __ Push(value.reg()); - } else if (value.IsConstant()) { - __ PushObject(value.constant()); - } else { - ASSERT(value.IsStackSlot()); - const intptr_t value_offset = value.ToStackSlotOffset(); - __ LoadFromOffset(TMP, value.base_reg(), value_offset); - __ Push(TMP); + if (previous()->IsPushArgument()) { + // Already generated. + return; } + ArgumentsPusher pusher; + for (PushArgumentInstr* push_arg = this; push_arg != nullptr; + push_arg = push_arg->next()->AsPushArgument()) { + const Location value = push_arg->locs()->in(0); + Register reg = kNoRegister; + if (value.IsRegister()) { + reg = value.reg(); + } else if (value.IsConstant()) { + if (compiler::IsSameObject(compiler::NullObject(), value.constant())) { + reg = NULL_REG; + } else { + reg = pusher.GetFreeTempRegister(); + __ LoadObject(reg, value.constant()); + } + } else { + ASSERT(value.IsStackSlot()); + const intptr_t value_offset = value.ToStackSlotOffset(); + reg = pusher.GetFreeTempRegister(); + __ LoadFromOffset(reg, value.base_reg(), value_offset); + } + pusher.PushRegister(compiler, reg); + } + pusher.Flush(compiler); } } @@ -814,11 +869,6 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, } } -LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, - bool opt) const { - return MakeCallSummary(zone); -} - void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { SetupNative(); const Register result = locs()->out(0).reg(); @@ -5094,12 +5144,6 @@ void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ Bind(&done); } -LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - return MakeCallSummary(zone); -} - LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { comparison()->InitializeLocationSummary(zone, opt); // Branches don't produce a result. diff --git a/runtime/vm/compiler/backend/il_deserializer.cc b/runtime/vm/compiler/backend/il_deserializer.cc index c84332dad86..6251bf8a179 100644 --- a/runtime/vm/compiler/backend/il_deserializer.cc +++ b/runtime/vm/compiler/backend/il_deserializer.cc @@ -294,16 +294,6 @@ FlowGraph* FlowGraphDeserializer::ParseFlowGraph() { pos++; } - // The graph entry doesn't push any arguments onto the stack. Adding a - // pushed_stack_map_ entry for it allows us to unify how function entries - // are handled vs. other types of blocks with regards to incoming pushed - // argument stacks. - // - // We add this entry now so that ParseEnvironment can assume that there's - // always a current pushed_stack_map_ for current_block_. - auto const empty_stack = new (zone()) PushStack(zone(), 0); - pushed_stack_map_.Insert(0, empty_stack); - // The deopt environment for the graph entry may use entries from the // constant pool, so that must be parsed first. if (auto const env_sexp = CheckList(root->ExtraLookupValue("env"))) { @@ -500,24 +490,9 @@ bool FlowGraphDeserializer::ParseBlocks(SExpList* list, auto const block_sexp = block_sexp_map.LookupValue(block_id); ASSERT(block_sexp != nullptr); - // Copy the pushed argument stack of the predecessor to begin the stack for - // this block. This is safe due to the worklist algorithm, since one - // predecessor has already been added when this block is first reached. - // - // For JoinEntry blocks, since the worklist algorithm is a depth-first - // search, we may not see all possible predecessors before the JoinEntry - // is parsed. To ensure consistency between predecessor stacks, we check - // the consistency in ParseBlockContents when updating predecessor - // information. current_block_ = block_map_.LookupValue(block_id); ASSERT(current_block_ != nullptr); ASSERT(current_block_->PredecessorCount() > 0); - auto const pred_id = current_block_->PredecessorAt(0)->block_id(); - auto const pred_stack = pushed_stack_map_.LookupValue(pred_id); - ASSERT(pred_stack != nullptr); - auto const new_stack = new (zone()) PushStack(zone(), pred_stack->length()); - new_stack->AddArray(*pred_stack); - pushed_stack_map_.Insert(block_id, new_stack); if (!ParseBlockContents(block_sexp, worklist)) return false; @@ -663,9 +638,6 @@ intptr_t FlowGraphDeserializer::SkipPhis(SExpList* list) { bool FlowGraphDeserializer::ParseBlockContents(SExpList* list, BlockWorklist* worklist) { ASSERT(current_block_ != nullptr); - auto const curr_stack = - pushed_stack_map_.LookupValue(current_block_->block_id()); - ASSERT(curr_stack != nullptr); // Parse any Phi definitions now before parsing the block environment. if (current_block_->IsJoinEntry()) { @@ -699,9 +671,6 @@ bool FlowGraphDeserializer::ParseBlockContents(SExpList* list, if (last_inst->SuccessorCount() > 0) { for (intptr_t i = last_inst->SuccessorCount() - 1; i >= 0; i--) { auto const succ_block = last_inst->SuccessorAt(i); - // Check and make sure the stack we have is consistent with stacks - // from other predecessors. - if (!AreStacksConsistent(list, curr_stack, succ_block)) return false; succ_block->AddPredecessor(current_block_); worklist->Add(succ_block->block_id()); } @@ -787,6 +756,7 @@ Instruction* FlowGraphDeserializer::ParseInstruction(SExpList* list) { // Parse the environment before handling the instruction, as we may have // references to PushArguments and parsing the instruction may pop // PushArguments off the stack. + // TODO(alexmarkov): revise as it may not be needed anymore. Environment* env = nullptr; if (auto const env_sexp = CheckList(list->ExtraLookupValue("env"))) { env = ParseEnvironment(env_sexp); @@ -1056,8 +1026,9 @@ InstanceCallInstr* FlowGraphDeserializer::DeserializeInstanceCall( SExpList* sexp, const InstrInfo& info) { auto& interface_target = Function::ZoneHandle(zone()); - if (!ParseDartValue(Retrieve(sexp, 1), &interface_target)) return nullptr; - + if (!ParseDartValue(Retrieve(sexp, "interface_target"), &interface_target)) { + return nullptr; + } auto& function_name = String::ZoneHandle(zone()); // If we have an explicit function_name value, then use that value. Otherwise, // if we have an non-null interface_target, use its name. @@ -1086,7 +1057,7 @@ InstanceCallInstr* FlowGraphDeserializer::DeserializeInstanceCall( } auto const inst = new (zone()) InstanceCallInstr( - info.token_pos, function_name, token_kind, call_info.arguments, + info.token_pos, function_name, token_kind, call_info.inputs, call_info.type_args_len, call_info.argument_names, checked_arg_count, info.deopt_id, interface_target); @@ -1129,7 +1100,7 @@ NativeCallInstr* FlowGraphDeserializer::DeserializeNativeCall( SExpList* sexp, const InstrInfo& info) { auto& function = Function::ZoneHandle(zone()); - if (!ParseDartValue(Retrieve(sexp, 1), &function)) return nullptr; + if (!ParseDartValue(Retrieve(sexp, "function"), &function)) return nullptr; if (!function.IsFunction()) { StoreError(sexp->At(1), "expected a Function value"); return nullptr; @@ -1149,7 +1120,7 @@ NativeCallInstr* FlowGraphDeserializer::DeserializeNativeCall( if (!ParseCallInfo(sexp, &call_info)) return nullptr; return new (zone()) NativeCallInstr(&name, &function, link_lazily, - info.token_pos, call_info.arguments); + info.token_pos, call_info.inputs); } ParameterInstr* FlowGraphDeserializer::DeserializeParameter( @@ -1162,18 +1133,6 @@ ParameterInstr* FlowGraphDeserializer::DeserializeParameter( return nullptr; } -PushArgumentInstr* FlowGraphDeserializer::DeserializePushArgument( - SExpList* sexp, - const InstrInfo& info) { - auto const val = ParseValue(Retrieve(sexp, 1)); - if (val == nullptr) return nullptr; - auto const push = new (zone()) PushArgumentInstr(val); - auto const stack = pushed_stack_map_.LookupValue(current_block_->block_id()); - ASSERT(stack != nullptr); - stack->Add(push); - return push; -} - ReturnInstr* FlowGraphDeserializer::DeserializeReturn(SExpList* list, const InstrInfo& info) { Value* val = ParseValue(Retrieve(list, 1)); @@ -1200,7 +1159,8 @@ StaticCallInstr* FlowGraphDeserializer::DeserializeStaticCall( SExpList* sexp, const InstrInfo& info) { auto& function = Function::ZoneHandle(zone()); - auto const function_sexp = CheckTaggedList(Retrieve(sexp, 1), "Function"); + auto const function_sexp = + CheckTaggedList(Retrieve(sexp, "function"), "Function"); if (!ParseFunction(function_sexp, &function)) return nullptr; CallInfo call_info(zone()); @@ -1223,8 +1183,8 @@ StaticCallInstr* FlowGraphDeserializer::DeserializeStaticCall( auto const inst = new (zone()) StaticCallInstr(info.token_pos, function, call_info.type_args_len, - call_info.argument_names, call_info.arguments, - info.deopt_id, call_count, rebind_rule); + call_info.argument_names, call_info.inputs, info.deopt_id, + call_count, rebind_rule); if (call_info.result_type != nullptr) { inst->SetResultType(zone(), *call_info.result_type); @@ -1298,7 +1258,9 @@ ThrowInstr* FlowGraphDeserializer::DeserializeThrow(SExpList* sexp, return new (zone()) ThrowInstr(info.token_pos, info.deopt_id, exception); } -bool FlowGraphDeserializer::ParseCallInfo(SExpList* call, CallInfo* out) { +bool FlowGraphDeserializer::ParseCallInfo(SExpList* call, + CallInfo* out, + intptr_t num_extra_inputs) { ASSERT(out != nullptr); if (auto const len_sexp = @@ -1336,8 +1298,14 @@ bool FlowGraphDeserializer::ParseCallInfo(SExpList* call, CallInfo* out) { // Type arguments are wrapped in a TypeArguments array, so no matter how // many there are, they are contained in a single pushed argument. auto const all_args_len = (out->type_args_len > 0 ? 1 : 0) + out->args_len; - out->arguments = FetchPushedArguments(call, all_args_len); - if (out->arguments == nullptr) return false; + + const intptr_t num_inputs = all_args_len + num_extra_inputs; + out->inputs = new (zone()) InputsArray(zone(), num_inputs); + for (intptr_t i = 0; i < num_inputs; ++i) { + auto const input = ParseValue(Retrieve(call, 1 + i)); + if (input == nullptr) return false; + out->inputs->Add(input); + } return true; } @@ -1435,24 +1403,11 @@ Environment* FlowGraphDeserializer::ParseEnvironment(SExpList* list) { auto const env = new (zone()) Environment(list->Length(), fixed_param_count, *parsed_function_, outer_env); - auto const stack = pushed_stack_map_.LookupValue(current_block_->block_id()); - ASSERT(stack != nullptr); for (intptr_t i = 0; i < list->Length(); i++) { auto const elem_sexp = Retrieve(list, i); if (elem_sexp == nullptr) return nullptr; auto val = ParseValue(elem_sexp, /*allow_pending=*/false); - if (val == nullptr) { - intptr_t index; - if (!ParseSymbolAsPrefixedInt(CheckSymbol(elem_sexp), 'a', &index)) { - StoreError(elem_sexp, "expected value or reference to pushed argument"); - return nullptr; - } - if (index >= stack->length()) { - StoreError(elem_sexp, "out of range index for pushed argument"); - return nullptr; - } - val = new (zone()) Value(stack->At(index)); - } + if (val == nullptr) return nullptr; env->PushValue(val); } @@ -2434,24 +2389,6 @@ bool FlowGraphDeserializer::FixPendingValues(intptr_t index, Definition* def) { return true; } -PushArgumentsArray* FlowGraphDeserializer::FetchPushedArguments(SExpList* list, - intptr_t len) { - auto const stack = pushed_stack_map_.LookupValue(current_block_->block_id()); - ASSERT(stack != nullptr); - auto const stack_len = stack->length(); - if (len > stack_len) { - StoreError(list, "expected %" Pd " pushed arguments, only %" Pd " on stack", - len, stack_len); - return nullptr; - } - auto const arr = new (zone()) PushArgumentsArray(zone(), len); - for (intptr_t i = 0; i < len; i++) { - arr->Add(stack->At(stack_len - len + i)); - } - stack->TruncateTo(stack_len - len); - return arr; -} - BlockEntryInstr* FlowGraphDeserializer::FetchBlock(SExpSymbol* sym) { if (sym == nullptr) return nullptr; intptr_t block_id; @@ -2464,43 +2401,6 @@ BlockEntryInstr* FlowGraphDeserializer::FetchBlock(SExpSymbol* sym) { return entry; } -bool FlowGraphDeserializer::AreStacksConsistent(SExpList* list, - PushStack* curr_stack, - BlockEntryInstr* succ_block) { - auto const curr_stack_len = curr_stack->length(); - for (intptr_t i = 0, n = succ_block->SuccessorCount(); i < n; i++) { - auto const pred_block = succ_block->PredecessorAt(i); - auto const pred_stack = - pushed_stack_map_.LookupValue(pred_block->block_id()); - ASSERT(pred_stack != nullptr); - if (pred_stack->length() != curr_stack_len) { - StoreError(list->At(1), - "current pushed stack has %" Pd - " elements, " - "other pushed stack for B%" Pd " has %" Pd "", - curr_stack_len, pred_block->block_id(), pred_stack->length()); - return false; - } - for (intptr_t i = 0; i < curr_stack_len; i++) { - // Leftover pushed arguments on the stack should come from dominating - // nodes, so they should be the same PushedArgumentInstr no matter the - // predecessor. - if (pred_stack->At(i) != curr_stack->At(i)) { - auto const pred_def = pred_stack->At(i)->value()->definition(); - auto const curr_def = curr_stack->At(i)->value()->definition(); - StoreError(list->At(1), - "current pushed stack has v%" Pd " at position %" Pd - ", " - "other pushed stack for B%" Pd " has v%" Pd "", - curr_def->ssa_temp_index(), i, pred_block->block_id(), - pred_def->ssa_temp_index()); - return false; - } - } - } - return true; -} - #define BASE_CHECK_DEF(name, type) \ SExp##name* FlowGraphDeserializer::Check##name(SExpression* sexp) { \ if (sexp == nullptr) return nullptr; \ diff --git a/runtime/vm/compiler/backend/il_deserializer.h b/runtime/vm/compiler/backend/il_deserializer.h index 08e6103240f..9e8d40b8c44 100644 --- a/runtime/vm/compiler/backend/il_deserializer.h +++ b/runtime/vm/compiler/backend/il_deserializer.h @@ -48,7 +48,6 @@ class FlowGraphDeserializer : ValueObject { root_sexp_(ASSERT_NOTNULL(root)), parsed_function_(pf), block_map_(zone), - pushed_stack_map_(zone), definition_map_(zone), values_map_(zone), recursive_types_map_(zone), @@ -103,7 +102,6 @@ class FlowGraphDeserializer : ValueObject { M(LoadField) \ M(NativeCall) \ M(Parameter) \ - M(PushArgument) \ M(Return) \ M(SpecialParameter) \ M(StaticCall) \ @@ -139,7 +137,6 @@ class FlowGraphDeserializer : ValueObject { bool ParseConstantPool(SExpList* pool); bool ParseEntries(SExpList* list); - using PushStack = ZoneGrowableArray; using BlockWorklist = GrowableArray; // Starts parsing the contents of [list], where the blocks begin at position @@ -231,14 +228,16 @@ class FlowGraphDeserializer : ValueObject { Array& argument_names; intptr_t type_args_len = 0; intptr_t args_len = 0; - PushArgumentsArray* arguments = nullptr; + InputsArray* inputs = nullptr; CompileType* result_type = nullptr; Code::EntryKind entry_kind = Code::EntryKind::kNormal; }; // Helper function for parsing call instructions that returns a structure // of information common to all calls. - bool ParseCallInfo(SExpList* call, CallInfo* out); + bool ParseCallInfo(SExpList* call, + CallInfo* out, + intptr_t num_extra_inputs = 0); // Parses [sexp] as a value form, that is, either the binding name for // a definition as a symbol or the form (value { ... }). @@ -314,25 +313,10 @@ class FlowGraphDeserializer : ValueObject { // Helper function for rebinding values pending on this definition. bool FixPendingValues(intptr_t index, Definition* def); - // Creates a PushArgumentsArray of size [len] from [pushed_stack_] if there - // are enough and pops the fetched arguments from the stack. - // - // The [sexp] argument should be the serialized form of the instruction that - // needs the pushed arguments and is only used for error reporting. - PushArgumentsArray* FetchPushedArguments(SExpList* sexp, intptr_t len); - // Retrieves the block corresponding to the given block ID symbol from // [block_map_]. Assumes all blocks have had their header parsed. BlockEntryInstr* FetchBlock(SExpSymbol* sym); - // Checks that the pushed argument stacks for all predecessors of [succ_block] - // are the same as [curr_stack]. This check ensures that we can choose an - // arbitrary predecessor's pushed argument stack when parsing [succ_block]'s - // contents. [list] is used for error reporting. - bool AreStacksConsistent(SExpList* list, - PushStack* curr_stack, - BlockEntryInstr* succ_block); - // Utility functions for checking the shape of an S-expression. // If these functions return nullptr for a non-null argument, they have the // side effect of setting the stored error message. @@ -370,12 +354,6 @@ class FlowGraphDeserializer : ValueObject { // available via [flow_graph_]. IntMap block_map_; - // Map from block IDs to pushed argument stacks. Used for PushArgument - // instructions, environment parsing, and calls during block parsing. Also - // used to check that the final pushed argument stacks for predecessor blocks - // are consistent when parsing a JoinEntry. - IntMap pushed_stack_map_; - // Map from variable indexes to definitions. IntMap definition_map_; diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc index 05d18eb6bb8..10f1149a768 100644 --- a/runtime/vm/compiler/backend/il_ia32.cc +++ b/runtime/vm/compiler/backend/il_ia32.cc @@ -82,7 +82,7 @@ LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode - // where PushArgument is handled by BindInstr::EmitNativeCode. + // where arguments are pushed by their definitions. if (compiler->is_optimizing()) { Location value = locs()->in(0); if (value.IsRegister()) { @@ -885,11 +885,6 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, } } -LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, - bool opt) const { - return MakeCallSummary(zone); -} - void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { SetupNative(); Register result = locs()->out(0).reg(); @@ -5354,12 +5349,6 @@ void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ SmiTag(EDX); } -LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - return MakeCallSummary(zone); -} - LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { comparison()->InitializeLocationSummary(zone, opt); // Branches don't produce a result. diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc index 04a116f1814..d039bf37506 100644 --- a/runtime/vm/compiler/backend/il_printer.cc +++ b/runtime/vm/compiler/backend/il_printer.cc @@ -489,7 +489,7 @@ void AssertBooleanInstr::PrintOperandsTo(BufferFormatter* f) const { void ClosureCallInstr::PrintOperandsTo(BufferFormatter* f) const { f->Print(" function="); - InputAt(0)->PrintTo(f); + InputAt(InputCount() - 1)->PrintTo(f); f->Print("<%" Pd ">", type_args_len()); for (intptr_t i = 0; i < ArgumentCount(); ++i) { f->Print(", "); diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc index 7ff875c3b04..e1032a2f19d 100644 --- a/runtime/vm/compiler/backend/il_serializer.cc +++ b/runtime/vm/compiler/backend/il_serializer.cc @@ -880,7 +880,7 @@ void FlowGraphSerializer::AddDefinitionExtraInfoToSExp(const Definition* def, SExpression* Definition::ToSExpression(FlowGraphSerializer* s) const { // If we don't have a temp index, then this is a Definition that has no - // usable result, like PushArgumentInstr. + // usable result. const bool binds_name = HasSSATemp() || HasTemp(); // Don't serialize non-binding definitions as definitions unless we either // have Definition-specific extra info or we're in verbose mode. @@ -1126,14 +1126,15 @@ void TailCallInstr::AddOperandsToSExpression(SExpList* sexp, void NativeCallInstr::AddOperandsToSExpression(SExpList* sexp, FlowGraphSerializer* s) const { - if (auto const func = s->DartValueToSExp(function())) { - sexp->Add(func); - } + Instruction::AddOperandsToSExpression(sexp, s); } void NativeCallInstr::AddExtraInfoToSExpression(SExpList* sexp, FlowGraphSerializer* s) const { TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s); + if (auto const func = s->DartValueToSExp(function())) { + sexp->AddExtra("function", func); + } if (!native_name().IsNull()) { s->AddExtraString(sexp, "name", native_name().ToCString()); } @@ -1142,8 +1143,8 @@ void NativeCallInstr::AddExtraInfoToSExpression(SExpList* sexp, } } -template -void TemplateDartCall::AddExtraInfoToSExpression( +template +void TemplateDartCall::AddExtraInfoToSExpression( SExpList* sexp, FlowGraphSerializer* s) const { Instruction::AddExtraInfoToSExpression(sexp, s); @@ -1162,6 +1163,8 @@ void TemplateDartCall::AddExtraInfoToSExpression( } sexp->AddExtra("arg_names", arg_names_sexp); } + + ASSERT(!HasPushArguments()); } void ClosureCallInstr::AddExtraInfoToSExpression(SExpList* sexp, @@ -1173,15 +1176,17 @@ void ClosureCallInstr::AddExtraInfoToSExpression(SExpList* sexp, void StaticCallInstr::AddOperandsToSExpression(SExpList* sexp, FlowGraphSerializer* s) const { - if (auto const func = s->DartValueToSExp(function())) { - sexp->Add(func); - } + Instruction::AddOperandsToSExpression(sexp, s); } void StaticCallInstr::AddExtraInfoToSExpression(SExpList* sexp, FlowGraphSerializer* s) const { TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s); + if (auto const func = s->DartValueToSExp(function())) { + sexp->AddExtra("function", func); + } + if (HasICData()) { sexp->AddExtra("ic_data", s->ICDataToSExp(ic_data())); } else if (CallCount() > 0 || FLAG_verbose_flow_graph_serialization) { @@ -1208,9 +1213,7 @@ void StaticCallInstr::AddExtraInfoToSExpression(SExpList* sexp, void InstanceCallInstr::AddOperandsToSExpression(SExpList* sexp, FlowGraphSerializer* s) const { - if (auto const target = s->DartValueToSExp(interface_target())) { - sexp->Add(target); - } + Instruction::AddOperandsToSExpression(sexp, s); } void InstanceCallInstr::AddExtraInfoToSExpression( @@ -1218,6 +1221,10 @@ void InstanceCallInstr::AddExtraInfoToSExpression( FlowGraphSerializer* s) const { TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s); + if (auto const target = s->DartValueToSExp(interface_target())) { + sexp->AddExtra("interface_target", target); + } + if (HasICData()) { sexp->AddExtra("ic_data", s->ICDataToSExp(ic_data())); } @@ -1254,13 +1261,16 @@ void InstanceCallInstr::AddExtraInfoToSExpression( void PolymorphicInstanceCallInstr::AddOperandsToSExpression( SExpList* sexp, FlowGraphSerializer* s) const { - sexp->Add(instance_call()->ToSExpression(s)); + Instruction::AddOperandsToSExpression(sexp, s); } void PolymorphicInstanceCallInstr::AddExtraInfoToSExpression( SExpList* sexp, FlowGraphSerializer* s) const { - Instruction::AddExtraInfoToSExpression(sexp, s); + TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s); + // TODO(alexmarkov): figure out how to serialize information from + // inner InstanceCall + // sexp->AddExtra("instance_call", instance_call()->ToSExpression(s)); if (targets().length() > 0 || FLAG_verbose_flow_graph_serialization) { auto elem_list = new (s->zone()) SExpList(s->zone()); for (intptr_t i = 0; i < targets().length(); i++) { @@ -1449,29 +1459,11 @@ void CompileType::AddExtraInfoToSExpression(SExpList* sexp, } } -// TODO(@sstrickl): find a better way, store stack index? -static intptr_t CountArgs(Environment* env) { - if (env != nullptr) { - intptr_t arg_count = CountArgs(env->outer()); - for (intptr_t i = 0, n = env->Length(); i < n; ++i) { - if (env->ValueAt(i)->definition()->IsPushArgument()) { - arg_count++; - } - } - return arg_count; - } - return 0; -} - SExpression* Environment::ToSExpression(FlowGraphSerializer* s) const { auto sexp = new (s->zone()) SExpList(s->zone()); - intptr_t arg_count = CountArgs(outer_); for (intptr_t i = 0; i < values_.length(); ++i) { - if (values_[i]->definition()->IsPushArgument()) { - s->AddSymbol(sexp, OS::SCreate(s->zone(), "a%" Pd "", arg_count++)); - } else { - sexp->Add(values_[i]->ToSExpression(s)); - } + ASSERT(!values_[i]->definition()->IsPushArgument()); + sexp->Add(values_[i]->ToSExpression(s)); // TODO(sstrickl): This currently assumes that there are no locations in the // environment (e.g. before register allocation). If we ever want to print // out environments on steps after AllocateRegisters, we'll need to handle diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index 1e514229833..43e04ddee3c 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -82,7 +82,7 @@ LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode - // where PushArgument is handled by BindInstr::EmitNativeCode. + // where arguments are pushed by their definitions. if (compiler->is_optimizing()) { Location value = locs()->in(0); if (value.IsRegister()) { @@ -888,11 +888,6 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, } } -LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, - bool opt) const { - return MakeCallSummary(zone); -} - void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { SetupNative(); Register result = locs()->out(0).reg(); @@ -5459,12 +5454,6 @@ void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // in-range arguments, cannot create out-of-range result. } -LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - return MakeCallSummary(zone); -} - LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { comparison()->InitializeLocationSummary(zone, opt); // Branches don't produce a result. diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc index 928b09f4b22..91c189642c7 100644 --- a/runtime/vm/compiler/backend/inliner.cc +++ b/runtime/vm/compiler/backend/inliner.cc @@ -203,6 +203,9 @@ class GraphInfoCollector : public ValueObject { // PushArgument instructions are eliminated. if (current->IsAllocateObject()) { instruction_count_ += current->InputCount(); + } else if (current->ArgumentCount() > 0) { + ASSERT(!current->HasPushArguments()); + instruction_count_ += current->ArgumentCount(); } if (current->IsInstanceCall() || current->IsStaticCall() || current->IsClosureCall()) { @@ -1360,13 +1363,7 @@ class CallSiteInliner : public ValueObject { ReplaceParameterStubs(zone(), caller_graph_, call_data, NULL); - // Remove push arguments of the call. - Definition* call = call_data->call; - for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { - PushArgumentInstr* push = call->PushArgumentAt(i); - push->ReplaceUsesWith(push->value()->definition()); - push->RemoveFromGraph(); - } + ASSERT(!call_data->call->HasPushArguments()); } static intptr_t CountConstants(const GrowableArray& arguments) { @@ -2054,16 +2051,10 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() { } } + ASSERT(!call_->HasPushArguments()); + // Handle any non-inlined variants. if (!non_inlined_variants_->is_empty()) { - // Move push arguments of the call. - for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) { - PushArgumentInstr* push = call_->PushArgumentAt(i); - push->ReplaceUsesWith(push->value()->definition()); - push->previous()->LinkTo(push->next()); - cursor->LinkTo(push); - cursor = push; - } PolymorphicInstanceCallInstr* fallback_call = PolymorphicInstanceCallInstr::FromCall(Z, call_, *non_inlined_variants_, call_->complete()); @@ -2077,16 +2068,8 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() { fallback_call); AppendInstruction(AppendInstruction(cursor, fallback_call), fallback_return); - fallback_call->RepairPushArgsInEnvironment(); exit_collector_->AddExit(fallback_return); cursor = nullptr; - } else { - // Remove push arguments of the call. - for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) { - PushArgumentInstr* push = call_->PushArgumentAt(i); - push->ReplaceUsesWith(push->value()->definition()); - push->RemoveFromGraph(); - } } return entry; } @@ -3365,12 +3348,8 @@ bool FlowGraphInliner::TryReplaceInstanceCallWithInline( flow_graph->AddExactnessGuard(call, receiver_cid); } - // Remove the original push arguments. - for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { - PushArgumentInstr* push = call->PushArgumentAt(i); - push->ReplaceUsesWith(push->value()->definition()); - push->RemoveFromGraph(); - } + ASSERT(!call->HasPushArguments()); + // Replace all uses of this definition with the result. if (call->HasUses()) { ASSERT(result != nullptr && result->HasSSATemp()); @@ -3419,12 +3398,7 @@ bool FlowGraphInliner::TryReplaceStaticCallWithInline( ASSERT((last != nullptr && result != nullptr) || (call->function().recognized_kind() == MethodRecognizer::kObjectConstructor)); - // Remove the original push arguments. - for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { - PushArgumentInstr* push = call->PushArgumentAt(i); - push->ReplaceUsesWith(push->value()->definition()); - push->RemoveFromGraph(); - } + ASSERT(!call->HasPushArguments()); // Replace all uses of this definition with the result. if (call->HasUses()) { ASSERT(result->HasSSATemp()); diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc index 7754486878d..1f008233f9e 100644 --- a/runtime/vm/compiler/backend/redundancy_elimination.cc +++ b/runtime/vm/compiler/backend/redundancy_elimination.cc @@ -1045,8 +1045,7 @@ class AliasedSet : public ZoneAllocated { for (Value* use = defn->input_use_list(); use != NULL; use = use->next_use()) { Instruction* instr = use->instruction(); - if (instr->IsPushArgument() || instr->IsCheckedSmiOp() || - instr->IsCheckedSmiComparison() || + if (instr->HasUnknownSideEffects() || (instr->IsStoreIndexed() && (use->use_index() == StoreIndexedInstr::kValuePos)) || instr->IsStoreStaticField() || instr->IsPhi()) { @@ -2831,9 +2830,7 @@ void AllocationSinking::EliminateAllocation(Definition* alloc) { alloc->RemoveFromGraph(); if (alloc->ArgumentCount() > 0) { ASSERT(alloc->ArgumentCount() == 1); - for (intptr_t i = 0; i < alloc->ArgumentCount(); ++i) { - alloc->PushArgumentAt(i)->RemoveFromGraph(); - } + ASSERT(!alloc->HasPushArguments()); } } @@ -3703,6 +3700,7 @@ void DeadCodeElimination::EliminateDeadCode(FlowGraph* flow_graph) { BlockEntryInstr* block = block_it.Current(); for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { Instruction* current = it.Current(); + ASSERT(!current->IsPushArgument()); // TODO(alexmarkov): take control dependencies into account and // eliminate dead branches/conditions. if (!CanEliminateInstruction(current, block)) { @@ -3739,9 +3737,7 @@ void DeadCodeElimination::EliminateDeadCode(FlowGraph* flow_graph) { for (Environment::DeepIterator it(current->env()); !it.Done(); it.Advance()) { Definition* input = it.CurrentValue()->definition(); - if (PushArgumentInstr* push_argument = input->AsPushArgument()) { - input = push_argument->value()->definition(); - } + ASSERT(!input->IsPushArgument()); if (input->HasSSATemp() && !live.Contains(input->ssa_temp_index())) { worklist.Add(input); live.Add(input->ssa_temp_index()); @@ -3768,39 +3764,13 @@ void DeadCodeElimination::EliminateDeadCode(FlowGraph* flow_graph) { if (!CanEliminateInstruction(current, block)) { continue; } - // Remove push arguments that correspond to non-live definitions. For - // example, if a call is removed but some of its PushArguments are also - // have environmental uses in other instructions, then those PushArguments - // linger in the graph. However, currently we only run DCE after the - // EliminateEnvironments pass, so we are guaranteed those PushArguments - // now have no uses. - // - // TODO(dartbug.com/39767): A better solution is to be able to remove - // these push arguments as soon as they go dead (i.e., during environment - // elimination) To do this, we'd need a way to go from PushArguments to - // the call in which they appear as an argument (if any), but we don't - // currently have that, so this fix papers over that for now. - if (auto const push_arg = current->AsPushArgument()) { - auto const def = push_arg->value()->definition(); - ASSERT(def->HasSSATemp()); - if (live.Contains(def->ssa_temp_index())) { - continue; - } - } + ASSERT(!current->IsPushArgument()); + ASSERT((current->ArgumentCount() == 0) || !current->HasPushArguments()); if (Definition* def = current->AsDefinition()) { if (def->HasSSATemp() && live.Contains(def->ssa_temp_index())) { continue; } } - // Remove PushArgument instructions corresponding to 'current'. - for (intptr_t i = 0, n = current->ArgumentCount(); i < n; ++i) { - PushArgumentInstr* push_arg = current->PushArgumentAt(i); - // If the definition referenced by a push argument to dead code is also - // dead, then we may have already removed it. - if (push_arg->previous() == nullptr) continue; - push_arg->ReplaceUsesWith(push_arg->value()->definition()); - push_arg->RemoveFromGraph(); - } current->UnuseAllInputs(); it.RemoveCurrentFromGraph(); } diff --git a/runtime/vm/compiler/backend/redundancy_elimination_test.cc b/runtime/vm/compiler/backend/redundancy_elimination_test.cc index 97edbe958c6..63916ddc33f 100644 --- a/runtime/vm/compiler/backend/redundancy_elimination_test.cc +++ b/runtime/vm/compiler/backend/redundancy_elimination_test.cc @@ -291,7 +291,7 @@ static void TestAliasingViaRedefinition( auto b1 = H.flow_graph()->graph_entry()->normal_entry(); AllocateObjectInstr* v0; LoadFieldInstr* v1; - PushArgumentInstr* push_v1; + StaticCallInstr* call; LoadFieldInstr* v4; ReturnInstr* ret; @@ -303,15 +303,12 @@ static void TestAliasingViaRedefinition( v1 = builder.AddDefinition( new LoadFieldInstr(new Value(v0), slot, TokenPosition::kNoSource)); auto v2 = builder.AddDefinition(make_redefinition(&S, H.flow_graph(), v0)); - auto args = new PushArgumentsArray(2); - push_v1 = builder.AddInstruction(new PushArgumentInstr(new Value(v1))); - args->Add(push_v1); + auto args = new InputsArray(2); + args->Add(new Value(v1)); if (make_it_escape) { - auto push_v2 = - builder.AddInstruction(new PushArgumentInstr(new Value(v2))); - args->Add(push_v2); + args->Add(new Value(v2)); } - builder.AddInstruction(new StaticCallInstr( + call = builder.AddInstruction(new StaticCallInstr( TokenPosition::kNoSource, blackhole, 0, Array::empty_array(), args, S.GetNextDeoptId(), 0, ICData::RebindRule::kStatic)); v4 = builder.AddDefinition( @@ -332,8 +329,7 @@ static void TestAliasingViaRedefinition( // v1 should have been removed from the graph and replaced with constant_null. EXPECT_PROPERTY(v1, it.next() == nullptr && it.previous() == nullptr); - EXPECT_PROPERTY(push_v1, - it.value()->definition() == H.flow_graph()->constant_null()); + EXPECT_PROPERTY(call, it.ArgumentAt(0) == H.flow_graph()->constant_null()); if (make_it_escape) { // v4 however should not be removed from the graph, because v0 escapes into @@ -467,7 +463,7 @@ static void TestAliasingViaStore( AllocateObjectInstr* v0; AllocateObjectInstr* v5; LoadFieldInstr* v1; - PushArgumentInstr* push_v1; + StaticCallInstr* call; LoadFieldInstr* v4; ReturnInstr* ret; @@ -486,22 +482,19 @@ static void TestAliasingViaStore( v1 = builder.AddDefinition( new LoadFieldInstr(new Value(v0), slot, TokenPosition::kNoSource)); auto v2 = builder.AddDefinition(make_redefinition(&S, H.flow_graph(), v5)); - push_v1 = builder.AddInstruction(new PushArgumentInstr(new Value(v1))); - auto args = new PushArgumentsArray(2); - args->Add(push_v1); + auto args = new InputsArray(2); + args->Add(new Value(v1)); if (make_it_escape) { auto v6 = builder.AddDefinition( new LoadFieldInstr(new Value(v2), slot, TokenPosition::kNoSource)); - auto push_v6 = - builder.AddInstruction(new PushArgumentInstr(new Value(v6))); - args->Add(push_v6); + args->Add(new Value(v6)); } else if (make_host_escape) { builder.AddInstruction(new StoreInstanceFieldInstr( slot, new Value(v2), new Value(v0), kEmitStoreBarrier, TokenPosition::kNoSource)); - args->Add(builder.AddInstruction(new PushArgumentInstr(new Value(v5)))); + args->Add(new Value(v5)); } - builder.AddInstruction(new StaticCallInstr( + call = builder.AddInstruction(new StaticCallInstr( TokenPosition::kNoSource, blackhole, 0, Array::empty_array(), args, S.GetNextDeoptId(), 0, ICData::RebindRule::kStatic)); v4 = builder.AddDefinition( @@ -528,8 +521,7 @@ static void TestAliasingViaStore( // v1 should have been removed from the graph and replaced with constant_null. EXPECT_PROPERTY(v1, it.next() == nullptr && it.previous() == nullptr); - EXPECT_PROPERTY(push_v1, - it.value()->definition() == H.flow_graph()->constant_null()); + EXPECT_PROPERTY(call, it.ArgumentAt(0) == H.flow_graph()->constant_null()); if (make_it_escape || make_host_escape) { // v4 however should not be removed from the graph, because v0 escapes into diff --git a/runtime/vm/compiler/backend/type_propagator_test.cc b/runtime/vm/compiler/backend/type_propagator_test.cc index 77272f1c3bf..02a82c8ba02 100644 --- a/runtime/vm/compiler/backend/type_propagator_test.cc +++ b/runtime/vm/compiler/backend/type_propagator_test.cc @@ -230,7 +230,7 @@ ISOLATE_UNIT_TEST_CASE(TypePropagator_Refinement) { new StaticCallInstr(TokenPosition::kNoSource, target_func, /*type_args_len=*/0, /*argument_names=*/Array::empty_array(), - new PushArgumentsArray(0), S.GetNextDeoptId(), + new InputsArray(0), S.GetNextDeoptId(), /*call_count=*/0, ICData::RebindRule::kStatic)); builder.AddInstruction(new GotoInstr(b4, S.GetNextDeoptId())); } diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc index 9e438387f45..7535d0e222e 100644 --- a/runtime/vm/compiler/call_specializer.cc +++ b/runtime/vm/compiler/call_specializer.cc @@ -208,12 +208,7 @@ void CallSpecializer::SpecializePolymorphicInstanceCall( void CallSpecializer::ReplaceCallWithResult(Definition* call, Instruction* replacement, Definition* result) { - // Remove the original push arguments. - for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { - PushArgumentInstr* push = call->PushArgumentAt(i); - push->ReplaceUsesWith(push->value()->definition()); - push->RemoveFromGraph(); - } + ASSERT(!call->HasPushArguments()); if (result == nullptr) { ASSERT(replacement->IsDefinition()); call->ReplaceWith(replacement->AsDefinition(), current_iterator()); @@ -1304,11 +1299,7 @@ void CallSpecializer::ReplaceWithInstanceOf(InstanceCallInstr* call) { // One result only. AddReceiverCheck(call); ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool); - for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { - PushArgumentInstr* push = call->PushArgumentAt(i); - push->ReplaceUsesWith(push->value()->definition()); - push->RemoveFromGraph(); - } + ASSERT(!call->HasPushArguments()); call->ReplaceUsesWith(bool_const); ASSERT(current_iterator()->Current() == call); current_iterator()->RemoveCurrentFromGraph(); diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc index ae48bcb704f..82f1c16340e 100644 --- a/runtime/vm/compiler/compiler_pass.cc +++ b/runtime/vm/compiler/compiler_pass.cc @@ -493,6 +493,7 @@ COMPILER_PASS(AllocationSinking_DetachMaterializations, { }); COMPILER_PASS(AllocateRegisters, { + flow_graph->InsertPushArguments(); // Ensure loop hierarchy has been computed. flow_graph->GetLoopHierarchy(); // Perform register allocation on the SSA graph. diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc index 6e5c7e85502..dd865889929 100644 --- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc +++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc @@ -434,13 +434,6 @@ Fragment BaseFlowGraphBuilder::NullConstant() { return Constant(Instance::ZoneHandle(Z, Instance::null())); } -Fragment BaseFlowGraphBuilder::PushArgument() { - PushArgumentInstr* argument = new (Z) PushArgumentInstr(Pop()); - Push(argument); - ++pending_argument_count_; - return Fragment(argument); -} - Fragment BaseFlowGraphBuilder::GuardFieldLength(const Field& field, intptr_t deopt_id) { return Fragment(new (Z) GuardFieldLengthInstr(Pop(), field, deopt_id)); @@ -622,9 +615,7 @@ LocalVariable* BaseFlowGraphBuilder::MakeTemporary() { // will not be cleared (causing them to never be materialized in the // expression stack and skew stack depth). for (Value* item = stack_; item != nullptr; item = item->next_use()) { - if (!item->definition()->IsPushArgument()) { - item->definition()->set_ssa_temp_index(0); - } + item->definition()->set_ssa_temp_index(0); } return variable; @@ -719,18 +710,12 @@ JoinEntryInstr* BaseFlowGraphBuilder::BuildJoinEntry() { GetNextDeoptId(), GetStackDepth()); } -ArgumentArray BaseFlowGraphBuilder::GetArguments(int count) { - ArgumentArray arguments = - new (Z) ZoneGrowableArray(Z, count); +InputsArray* BaseFlowGraphBuilder::GetArguments(int count) { + InputsArray* arguments = new (Z) ZoneGrowableArray(Z, count); arguments->SetLength(count); for (intptr_t i = count - 1; i >= 0; --i) { - ASSERT(stack_->definition()->IsPushArgument()); - ASSERT(!stack_->definition()->HasSSATemp()); - arguments->data()[i] = stack_->definition()->AsPushArgument(); - Drop(); + arguments->data()[i] = Pop(); } - pending_argument_count_ -= count; - ASSERT(pending_argument_count_ >= 0); return arguments; } @@ -1035,11 +1020,8 @@ Fragment BaseFlowGraphBuilder::BuildEntryPointsIntrospection() { Fragment call_hook; call_hook += Constant(closure); - call_hook += PushArgument(); call_hook += Constant(function_name); - call_hook += PushArgument(); call_hook += LoadLocal(entry_point_num); - call_hook += PushArgument(); call_hook += Constant(Function::ZoneHandle(Z, closure.function())); call_hook += ClosureCall(TokenPosition::kNoSource, /*type_args_len=*/0, /*argument_count=*/3, @@ -1054,14 +1036,12 @@ Fragment BaseFlowGraphBuilder::ClosureCall(TokenPosition position, intptr_t argument_count, const Array& argument_names, bool is_statically_checked) { - Value* function = Pop(); - const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0); - ArgumentArray arguments = GetArguments(total_count); - ClosureCallInstr* call = new (Z) - ClosureCallInstr(function, arguments, type_args_len, argument_names, - position, GetNextDeoptId(), - is_statically_checked ? Code::EntryKind::kUnchecked - : Code::EntryKind::kNormal); + const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0) + 1; + InputsArray* arguments = GetArguments(total_count); + ClosureCallInstr* call = new (Z) ClosureCallInstr( + arguments, type_args_len, argument_names, position, GetNextDeoptId(), + is_statically_checked ? Code::EntryKind::kUnchecked + : Code::EntryKind::kNormal); Push(call); return Fragment(call); } diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h index 17554e9666e..55af9c7985c 100644 --- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h +++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h @@ -106,8 +106,6 @@ class TestFragment { SuccessorAddressArray* false_successor_addresses = nullptr; }; -typedef ZoneGrowableArray* ArgumentArray; - // Indicates which form of the unchecked entrypoint we are compiling. // // kNone: @@ -154,7 +152,6 @@ class BaseFlowGraphBuilder { current_try_index_(kInvalidTryIndex), next_used_try_index_(0), stack_(NULL), - pending_argument_count_(0), exit_collector_(exit_collector), inlining_unchecked_entry_(inlining_unchecked_entry) {} @@ -233,8 +230,7 @@ class BaseFlowGraphBuilder { // LocalVariable* MakeTemporary(); - Fragment PushArgument(); - ArgumentArray GetArguments(int count); + InputsArray* GetArguments(int count); TargetEntryInstr* BuildTargetEntry(); FunctionEntryInstr* BuildFunctionEntry(GraphEntryInstr* graph_entry); @@ -432,7 +428,6 @@ class BaseFlowGraphBuilder { intptr_t next_used_try_index_; Value* stack_; - intptr_t pending_argument_count_; InlineExitCollector* exit_collector_; const bool inlining_unchecked_entry_; diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc index e5461257088..98a38efbcd0 100644 --- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc +++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc @@ -434,31 +434,6 @@ bool BytecodeFlowGraphBuilder::IsStackEmpty() const { return B->GetStackDepth() == 0; } -ArgumentArray BytecodeFlowGraphBuilder::GetArguments(int count) { - ArgumentArray arguments = - new (Z) ZoneGrowableArray(Z, count); - arguments->SetLength(count); - for (intptr_t i = count - 1; i >= 0; --i) { - ASSERT(!IsStackEmpty()); - Definition* arg_def = B->stack_->definition(); - ASSERT(arg_def->temp_index() >= i); - - PushArgumentInstr* argument = new (Z) PushArgumentInstr(Pop()); - - if (code_.current == arg_def) { - code_ <<= argument; - } else { - Instruction* next = arg_def->next(); - ASSERT(next != nullptr); - arg_def->LinkTo(argument); - argument->LinkTo(next); - } - - arguments->data()[i] = argument; - } - return arguments; -} - InferredTypeMetadata BytecodeFlowGraphBuilder::GetInferredType(intptr_t pc) { ASSERT(!inferred_types_attribute_.IsNull()); intptr_t i = inferred_types_index_; @@ -890,7 +865,7 @@ void BytecodeFlowGraphBuilder::BuildDirectCallCommon(bool is_unchecked_call) { Array::Cast(ConstantAt(DecodeOperandD(), 1).value()); const ArgumentsDescriptor arg_desc(arg_desc_array); - ArgumentArray arguments = GetArguments(argc); + InputsArray* arguments = B->GetArguments(argc); StaticCallInstr* call = new (Z) StaticCallInstr( position_, target, arg_desc.TypeArgsLen(), @@ -970,7 +945,7 @@ void BytecodeFlowGraphBuilder::BuildInterfaceCallCommon( &checked_argument_count); const intptr_t argc = DecodeOperandF().value(); - const ArgumentArray arguments = GetArguments(argc); + InputsArray* arguments = B->GetArguments(argc); InstanceCallInstr* call = new (Z) InstanceCallInstr( position_, name, token_kind, arguments, arg_desc.TypeArgsLen(), @@ -1036,12 +1011,11 @@ void BytecodeFlowGraphBuilder::BuildUncheckedClosureCall() { /*clear_temp=*/false); code_ += B->LoadNativeField(Slot::Closure_function()); - Value* function = Pop(); - const ArgumentArray arguments = GetArguments(argc); + InputsArray* arguments = B->GetArguments(argc + 1); ClosureCallInstr* call = new (Z) ClosureCallInstr( - function, arguments, arg_desc.TypeArgsLen(), + arguments, arg_desc.TypeArgsLen(), Array::ZoneHandle(Z, arg_desc.GetArgumentNames()), position_, B->GetNextDeoptId(), Code::EntryKind::kUnchecked); @@ -1074,7 +1048,7 @@ void BytecodeFlowGraphBuilder::BuildDynamicCall() { &checked_argument_count); const intptr_t argc = DecodeOperandF().value(); - const ArgumentArray arguments = GetArguments(argc); + InputsArray* arguments = B->GetArguments(argc); const Function& interface_target = Function::null_function(); @@ -1105,7 +1079,7 @@ void BytecodeFlowGraphBuilder::BuildNativeCall() { const auto& name = String::ZoneHandle(Z, function().native_name()); const intptr_t num_args = function().NumParameters() + (function().IsGeneric() ? 1 : 0); - ArgumentArray arguments = GetArguments(num_args); + InputsArray* arguments = B->GetArguments(num_args); auto* call = new (Z) NativeCallInstr(&name, &function(), FLAG_link_natives_lazily, function().end_token_pos(), arguments); @@ -1783,7 +1757,7 @@ void BytecodeFlowGraphBuilder::BuildPrimitiveOp( // A DebugStepCheck is performed as part of the calling stub. LoadStackSlots(num_args); - const ArgumentArray arguments = GetArguments(num_args); + InputsArray* arguments = B->GetArguments(num_args); InstanceCallInstr* call = new (Z) InstanceCallInstr( position_, name, token_kind, arguments, 0, Array::null_array(), num_args, diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h index 2739cb6bdbe..03a19ab3a70 100644 --- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h +++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h @@ -159,7 +159,6 @@ class BytecodeFlowGraphBuilder { Value* Pop(); intptr_t GetStackDepth() const; bool IsStackEmpty() const; - ArgumentArray GetArguments(int count); InferredTypeMetadata GetInferredType(intptr_t pc); void PropagateStackState(intptr_t target_pc); void DropUnusedValuesFromStack(); diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index ae84ac85ac9..b4f6ad20f2d 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -364,7 +364,6 @@ Fragment StreamingFlowGraphBuilder::BuildInitializers( ReadCanonicalNameReference(); // read target_reference. instructions += LoadLocal(parsed_function()->receiver_var()); - instructions += PushArgument(); // TODO(jensj): ASSERT(init->arguments()->types().length() == 0); Array& argument_names = Array::ZoneHandle(Z); @@ -391,7 +390,6 @@ Fragment StreamingFlowGraphBuilder::BuildInitializers( ReadCanonicalNameReference(); // read target_reference. instructions += LoadLocal(parsed_function()->receiver_var()); - instructions += PushArgument(); // TODO(jensj): ASSERT(init->arguments()->types().length() == 0); Array& argument_names = Array::ZoneHandle(Z); @@ -535,7 +533,6 @@ Fragment StreamingFlowGraphBuilder::SetAsyncStackTrace( Fragment code; code += LoadLocal(async_stack_trace_var); - code += PushArgument(); // Call _asyncSetThreadStackTrace code += StaticCall(TokenPosition::kNoSource, target, /* argument_count = */ 1, ICData::kStatic); @@ -560,15 +557,14 @@ Fragment StreamingFlowGraphBuilder::TypeArgumentsHandling( if (dart_function.IsGeneric()) { prologue += LoadLocal(fn_type_args); - prologue += PushArgument(); + prologue += LoadLocal(closure); prologue += LoadNativeField(Slot::Closure_function_type_arguments()); - prologue += PushArgument(); + prologue += IntConstant(dart_function.NumParentTypeParameters()); - prologue += PushArgument(); + prologue += IntConstant(dart_function.NumTypeParameters() + dart_function.NumParentTypeParameters()); - prologue += PushArgument(); const Library& dart_internal = Library::Handle(Z, Library::InternalLibrary()); @@ -1627,10 +1623,6 @@ Fragment StreamingFlowGraphBuilder::Return(TokenPosition position, yield_index); } -Fragment StreamingFlowGraphBuilder::PushArgument() { - return flow_graph_builder_->PushArgument(); -} - Fragment StreamingFlowGraphBuilder::EvaluateAssertion() { return flow_graph_builder_->EvaluateAssertion(); } @@ -2059,9 +2051,7 @@ const TypeArguments& StreamingFlowGraphBuilder::BuildTypeArguments() { Fragment StreamingFlowGraphBuilder::BuildArguments(Array* argument_names, intptr_t* argument_count, - intptr_t* positional_count, - bool skip_push_arguments, - bool do_drop) { + intptr_t* positional_count) { intptr_t dummy; if (argument_count == NULL) argument_count = &dummy; *argument_count = ReadUInt(); // read arguments count. @@ -2074,22 +2064,17 @@ Fragment StreamingFlowGraphBuilder::BuildArguments(Array* argument_names, if (positional_count == NULL) positional_count = &dummy; *positional_count = ReadListLength(); // read length of expression list } - return BuildArgumentsFromActualArguments(argument_names, skip_push_arguments, - do_drop); + return BuildArgumentsFromActualArguments(argument_names); } Fragment StreamingFlowGraphBuilder::BuildArgumentsFromActualArguments( - Array* argument_names, - bool skip_push_arguments, - bool do_drop) { + Array* argument_names) { Fragment instructions; // List of positional. intptr_t list_length = ReadListLength(); // read list length. for (intptr_t i = 0; i < list_length; ++i) { instructions += BuildExpression(); // read ith expression. - if (!skip_push_arguments) instructions += PushArgument(); - if (do_drop) instructions += Drop(); } // List of named. @@ -2101,8 +2086,6 @@ Fragment StreamingFlowGraphBuilder::BuildArgumentsFromActualArguments( String& name = H.DartSymbolObfuscate(ReadStringReference()); // read ith name index. instructions += BuildExpression(); // read ith expression. - if (!skip_push_arguments) instructions += PushArgument(); - if (do_drop) instructions += Drop(); if (argument_names != NULL) { argument_names->SetAt(i, name); } @@ -2270,8 +2253,6 @@ Fragment StreamingFlowGraphBuilder::BuildPropertyGet(TokenPosition* p) { instructions += LoadLocal(receiver); } - instructions += PushArgument(); - const String& getter_name = ReadNameAsGetterName(); // read name. const Function* interface_target = &Function::null_function(); @@ -2346,13 +2327,10 @@ Fragment StreamingFlowGraphBuilder::BuildPropertySet(TokenPosition* p) { instructions += LoadLocal(receiver); } - instructions += PushArgument(); - const String& setter_name = ReadNameAsSetterName(); // read name. instructions += BuildExpression(); // read value. instructions += StoreLocal(TokenPosition::kNoSource, variable); - instructions += PushArgument(); const Function* interface_target = &Function::null_function(); const NameIndex itarget_name = @@ -2443,27 +2421,22 @@ Fragment StreamingFlowGraphBuilder::BuildAllocateInvocationMirrorCall( // First argument is receiver. instructions += LoadLocal(parsed_function()->receiver_var()); - instructions += PushArgument(); // Push the arguments for allocating the invocation mirror: // - the name. instructions += Constant(String::ZoneHandle(Z, name.raw())); - instructions += PushArgument(); // - the arguments descriptor. const Array& args_descriptor = Array::Handle(Z, ArgumentsDescriptor::New(num_type_arguments, num_arguments, argument_names)); instructions += Constant(Array::ZoneHandle(Z, args_descriptor.raw())); - instructions += PushArgument(); // - an array containing the actual arguments. instructions += LoadLocal(actuals_array); - instructions += PushArgument(); // - [true] indicating this is a `super` NoSuchMethod. instructions += Constant(Bool::True()); - instructions += PushArgument(); const Class& mirror_class = Class::Handle(Z, Library::LookupCoreClass(Symbols::InvocationMirror())); @@ -2531,7 +2504,6 @@ Fragment StreamingFlowGraphBuilder::BuildSuperPropertyGet(TokenPosition* p) { /* num_arguments = */ 1, /* argument_names = */ Object::empty_array(), actuals_array, /* build_rest_of_actuals = */ Fragment()); - instructions += PushArgument(); // second argument is invocation mirror Function& nsm_function = GetNoSuchMethodOrDie(Z, parent_klass); instructions += @@ -2543,7 +2515,6 @@ Fragment StreamingFlowGraphBuilder::BuildSuperPropertyGet(TokenPosition* p) { ASSERT(!function.IsNull()); instructions += LoadLocal(parsed_function()->receiver_var()); - instructions += PushArgument(); instructions += StaticCall(position, Function::ZoneHandle(Z, function.raw()), @@ -2587,7 +2558,6 @@ Fragment StreamingFlowGraphBuilder::BuildSuperPropertySet(TokenPosition* p) { /* num_arguments = */ 2, /* argument_names = */ Object::empty_array(), actuals_array, build_rest_of_actuals); - instructions += PushArgument(); // second argument - invocation mirror SkipCanonicalNameReference(); // skip target_reference. @@ -2600,11 +2570,9 @@ Fragment StreamingFlowGraphBuilder::BuildSuperPropertySet(TokenPosition* p) { } else { // receiver instructions += LoadLocal(parsed_function()->receiver_var()); - instructions += PushArgument(); instructions += BuildExpression(); // read value. instructions += StoreLocal(position, value); - instructions += PushArgument(); SkipCanonicalNameReference(); // skip target_reference. @@ -2665,7 +2633,6 @@ Fragment StreamingFlowGraphBuilder::BuildDirectPropertyGet(TokenPosition* p) { ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction()); } - instructions += PushArgument(); // 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. @@ -2683,7 +2650,6 @@ Fragment StreamingFlowGraphBuilder::BuildDirectPropertySet(TokenPosition* p) { LocalVariable* value = MakeTemporary(); instructions += BuildExpression(); // read receiver. - instructions += PushArgument(); const NameIndex target_reference = ReadCanonicalNameReference(); // read target_reference. @@ -2694,7 +2660,6 @@ Fragment StreamingFlowGraphBuilder::BuildDirectPropertySet(TokenPosition* p) { instructions += BuildExpression(); // read value. instructions += StoreLocal(TokenPosition::kNoSource, value); - instructions += PushArgument(); // Static calls are marked as "no-rebind", which is currently safe because // DirectPropertyGet are only used in enums (index in toString) and enums @@ -2789,7 +2754,6 @@ Fragment StreamingFlowGraphBuilder::BuildStaticSet(TokenPosition* p) { LocalVariable* variable = MakeTemporary(); instructions += LoadLocal(variable); if (!setter.IsNull() && field.NeedsSetter()) { - instructions += PushArgument(); instructions += StaticCall(position, setter, 1, ICData::kStatic); instructions += Drop(); } else { @@ -2805,7 +2769,6 @@ Fragment StreamingFlowGraphBuilder::BuildStaticSet(TokenPosition* p) { // Prepare argument. instructions += LoadLocal(variable); - instructions += PushArgument(); // Invoke the setter function. const Function& function = @@ -2866,8 +2829,6 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) { // type arguments here we need to push it between receiver_temp // and actual receiver. See the code below. type_arguments_temp = MakeTemporary(); - } else { - instructions += PushArgument(); } } type_args_len = list_length; @@ -2891,9 +2852,9 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) { PeekArgumentsFirstPositionalTag() == kNullLiteral)) { ASSERT(type_args_len == 0); // "==" or "!=" with null on either side. - instructions += BuildArguments(NULL /* named */, NULL /* arg count */, - NULL /* positional arg count */, - true); // read arguments. + instructions += + BuildArguments(NULL /* named */, NULL /* arg count */, + NULL /* positional arg count */); // read arguments. SkipCanonicalNameReference(); // read interface_target_reference. Token::Kind strict_cmp_kind = token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT; @@ -2912,13 +2873,10 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) { // [type_arguments_temp][receiver_temp][type_arguments][receiver] ... // instructions += LoadLocal(type_arguments_temp); - instructions += PushArgument(); } instructions += LoadLocal(receiver_temp); } - instructions += PushArgument(); // push receiver as argument. - intptr_t argument_count; intptr_t positional_argument_count; Array& argument_names = Array::ZoneHandle(Z); @@ -3046,7 +3004,6 @@ Fragment StreamingFlowGraphBuilder::BuildDirectMethodInvocation( const TypeArguments& type_arguments = T.BuildTypeArguments(list_length); // read types. instructions += TranslateInstantiatedTypeArguments(type_arguments); - instructions += PushArgument(); } type_args_len = list_length; } @@ -3066,17 +3023,15 @@ Fragment StreamingFlowGraphBuilder::BuildDirectMethodInvocation( PeekArgumentsFirstPositionalTag() == kNullLiteral)) { ASSERT(type_args_len == 0); // "==" or "!=" with null on either side. - instructions += BuildArguments(NULL /* names */, NULL /* arg count */, - NULL /* positional arg count */, - true); // read arguments. + instructions += + BuildArguments(NULL /* names */, NULL /* arg count */, + NULL /* positional arg count */); // read arguments. Token::Kind strict_cmp_kind = token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT; return instructions + StrictCompare(position, strict_cmp_kind, /*number_check = */ true); } - instructions += PushArgument(); // push receiver as argument. - const Function& target = Function::ZoneHandle(Z, H.LookupMethodByMember(kernel_name, method_name)); @@ -3190,7 +3145,6 @@ Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation( position, method_name, type_list_length, /* num_arguments = */ argument_count + 1, argument_names, actuals_array, build_rest_of_actuals); - instructions += PushArgument(); // second argument - invocation mirror SkipCanonicalNameReference(); // skip target_reference. @@ -3211,13 +3165,11 @@ Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation( const TypeArguments& type_arguments = T.BuildTypeArguments(list_length); // read types. instructions += TranslateInstantiatedTypeArguments(type_arguments); - instructions += PushArgument(); } } // receiver instructions += LoadLocal(parsed_function()->receiver_var()); - instructions += PushArgument(); Array& argument_names = Array::ZoneHandle(Z); intptr_t argument_count; @@ -3304,7 +3256,6 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) { instance_variable = MakeTemporary(); instructions += LoadLocal(instance_variable); - instructions += PushArgument(); } else if (target.IsFactory()) { // The VM requires currently a TypeArguments object as first parameter for // every factory constructor :-/ ! @@ -3313,7 +3264,6 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) { // into Kernel. const TypeArguments& type_arguments = PeekArgumentsInstantiatedType(klass); instructions += TranslateInstantiatedTypeArguments(type_arguments); - instructions += PushArgument(); } else if (!special_case) { AlternativeReadingScope alt(&reader_); ReadUInt(); // read argument count. @@ -3322,15 +3272,14 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) { const TypeArguments& type_arguments = T.BuildTypeArguments(list_length); // read types. instructions += TranslateInstantiatedTypeArguments(type_arguments); - instructions += PushArgument(); } type_args_len = list_length; } Array& argument_names = Array::ZoneHandle(Z); - instructions += BuildArguments(&argument_names, NULL /* arg count */, - NULL /* positional arg count */, - special_case); // read arguments. + instructions += + BuildArguments(&argument_names, NULL /* arg count */, + NULL /* positional arg count */); // read arguments. ASSERT(target.AreValidArguments(NNBDMode::kLegacyLib, type_args_len, argument_count, argument_names, NULL)); @@ -3400,7 +3349,6 @@ Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation( LocalVariable* variable = MakeTemporary(); instructions += LoadLocal(variable); - instructions += PushArgument(); Array& argument_names = Array::ZoneHandle(Z); intptr_t argument_count; @@ -3633,12 +3581,9 @@ Fragment StreamingFlowGraphBuilder::BuildIsExpression(TokenPosition* p) { // Let condition be always true. instructions += Constant(Bool::True()); } else { - instructions += PushArgument(); - // See if simple instanceOf is applicable. if (dart::SimpleInstanceOfType(type)) { instructions += Constant(type); - instructions += PushArgument(); // Type. instructions += InstanceCall( position, Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()), Token::kIS, 2, 2); // 2 checked arguments. @@ -3650,20 +3595,16 @@ Fragment StreamingFlowGraphBuilder::BuildIsExpression(TokenPosition* p) { } else { instructions += NullConstant(); } - instructions += PushArgument(); // Instantiator type arguments. if (!type.IsInstantiated(kFunctions)) { instructions += LoadFunctionTypeArguments(); } else { instructions += NullConstant(); } - instructions += PushArgument(); // Function type arguments. instructions += Constant(type); - instructions += PushArgument(); // Type. instructions += IntConstant(static_cast(nnbd_mode)); - instructions += PushArgument(); // nnbd_mode. instructions += InstanceCall( position, Library::PrivateCoreLibName(Symbols::_instanceOf()), @@ -3771,7 +3712,6 @@ Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition* p) { LocalVariable* type = MakeTemporary(); instructions += LoadLocal(type); - instructions += PushArgument(); if (length == 0) { instructions += Constant(Object::empty_array()); } else { @@ -3788,7 +3728,6 @@ Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition* p) { instructions += StoreIndexed(kArrayCid); } } - instructions += PushArgument(); // The array. const Class& factory_class = Class::Handle(Z, Library::LookupCoreClass(Symbols::List())); @@ -3810,7 +3749,6 @@ Fragment StreamingFlowGraphBuilder::BuildMapLiteral(TokenPosition* p) { // The type argument for the factory call `new Map._fromLiteral(List)`. Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments); - instructions += PushArgument(); intptr_t length = ReadListLength(); // read list length. // Note: there will be "length" map entries (i.e. key and value expressions). @@ -3838,7 +3776,6 @@ Fragment StreamingFlowGraphBuilder::BuildMapLiteral(TokenPosition* p) { instructions += StoreIndexed(kArrayCid); } } - instructions += PushArgument(); // The array. const Class& map_class = Class::Handle(Z, Library::LookupCoreClass(Symbols::Map())); @@ -3954,7 +3891,6 @@ Fragment StreamingFlowGraphBuilder::BuildFutureNullValue( Fragment instructions; instructions += BuildNullLiteral(position); - instructions += PushArgument(); instructions += StaticCall(TokenPosition::kNoSource, constructor, /* argument_count = */ 1, ICData::kStatic); return instructions; @@ -4000,9 +3936,7 @@ Fragment StreamingFlowGraphBuilder::BuildPartialTearoffInstantiation( // when the closure is coming from a tearoff of a top-level method or from a // local closure. instructions += LoadLocal(original_closure); - instructions += PushArgument(); instructions += LoadLocal(type_args_vec); - instructions += PushArgument(); const Library& dart_internal = Library::Handle(Z, Library::InternalLibrary()); const Function& bounds_check_function = Function::ZoneHandle( Z, dart_internal.LookupFunctionAllowPrivate( @@ -4137,7 +4071,6 @@ Fragment StreamingFlowGraphBuilder::BuildAssertStatement() { const TokenPosition condition_end_offset = ReadPosition(); // read condition end offset. - instructions += PushArgument(); instructions += EvaluateAssertion(); instructions += CheckBoolean(condition_start_offset); instructions += Constant(Bool::True()); @@ -4157,16 +4090,13 @@ Fragment StreamingFlowGraphBuilder::BuildAssertStatement() { // or Throw). Fragment otherwise_fragment(otherwise); otherwise_fragment += IntConstant(condition_start_offset.Pos()); - otherwise_fragment += PushArgument(); // start otherwise_fragment += IntConstant(condition_end_offset.Pos()); - otherwise_fragment += PushArgument(); // end Tag tag = ReadTag(); // read (first part of) message. if (tag == kSomething) { otherwise_fragment += BuildExpression(); // read (rest of) message. } else { otherwise_fragment += Constant(Instance::ZoneHandle(Z)); // null. } - otherwise_fragment += PushArgument(); // message // Note: condition_start_offset points to the first token after the opening // paren, not the beginning of 'assert'. @@ -4373,7 +4303,6 @@ Fragment StreamingFlowGraphBuilder::BuildForInStatement(bool async) { TokenPosition iterable_position = TokenPosition::kNoSource; Fragment instructions = BuildExpression(&iterable_position); // read iterable. - instructions += PushArgument(); const String& iterator_getter = String::ZoneHandle(Z, Field::GetterSymbol(Symbols::Iterator())); @@ -4386,7 +4315,6 @@ Fragment StreamingFlowGraphBuilder::BuildForInStatement(bool async) { for_in_depth_inc(); loop_depth_inc(); Fragment condition = LoadLocal(iterator); - condition += PushArgument(); condition += InstanceCall(iterable_position, Symbols::MoveNext(), Token::kILLEGAL, 1); TargetEntryInstr* body_entry; @@ -4396,7 +4324,6 @@ Fragment StreamingFlowGraphBuilder::BuildForInStatement(bool async) { Fragment body(body_entry); body += EnterScope(offset); body += LoadLocal(iterator); - body += PushArgument(); const String& current_getter = String::ZoneHandle(Z, Field::GetterSymbol(Symbols::Current())); body += InstanceCall(body_position, current_getter, Token::kGET, 1); @@ -4493,14 +4420,9 @@ Fragment StreamingFlowGraphBuilder::BuildSwitchStatement() { LocalVariable* instance = MakeTemporary(); // Call _FallThroughError._create constructor. - body_fragment += LoadLocal(instance); - body_fragment += PushArgument(); // this - - body_fragment += Constant(url); - body_fragment += PushArgument(); // url - - body_fragment += NullConstant(); - body_fragment += PushArgument(); // line + body_fragment += LoadLocal(instance); // this + body_fragment += Constant(url); // url + body_fragment += NullConstant(); // line body_fragment += StaticCall(TokenPosition::kNoSource, constructor, 3, ICData::kStatic); @@ -4566,9 +4488,7 @@ Fragment StreamingFlowGraphBuilder::BuildSwitchStatement() { TokenPosition position = ReadPosition(); // read jth position. current_instructions += Constant( Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression())); - current_instructions += PushArgument(); current_instructions += LoadLocal(scopes()->switch_variable); - current_instructions += PushArgument(); current_instructions += InstanceCall(position, Symbols::EqualOperator(), Token::kEQ, /*argument_count=*/2, @@ -4788,24 +4708,24 @@ Fragment StreamingFlowGraphBuilder::BuildTryCatch() { if (type_guard != NULL) { catch_body += LoadLocal(CurrentException()); - catch_body += PushArgument(); // exception + if (!type_guard->IsInstantiated(kCurrentClass)) { catch_body += LoadInstantiatorTypeArguments(); } else { catch_body += NullConstant(); } - catch_body += PushArgument(); // instantiator type arguments + if (!type_guard->IsInstantiated(kFunctions)) { catch_body += LoadFunctionTypeArguments(); } else { catch_body += NullConstant(); } - catch_body += PushArgument(); // function type arguments + catch_body += Constant(*type_guard); - catch_body += PushArgument(); // guard type + const NNBDMode nnbd_mode = parsed_function()->function().nnbd_mode(); catch_body += IntConstant(static_cast(nnbd_mode)); - catch_body += PushArgument(); // nnbd_mode + catch_body += InstanceCall( position, Library::PrivateCoreLibName(Symbols::_instanceOf()), Token::kIS, 5); diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h index 99aeaa024fd..65b29184409 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h @@ -158,7 +158,6 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper { Fragment LoadLocal(LocalVariable* variable); Fragment Return(TokenPosition position, intptr_t yield_index = RawPcDescriptors::kInvalidYieldIndex); - Fragment PushArgument(); Fragment EvaluateAssertion(); Fragment RethrowException(TokenPosition position, int catch_try_index); Fragment ThrowNoSuchMethodError(); @@ -268,12 +267,8 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper { const TypeArguments& BuildTypeArguments(); Fragment BuildArguments(Array* argument_names, intptr_t* argument_count, - intptr_t* positional_argument_count, - bool skip_push_arguments = false, - bool do_drop = false); - Fragment BuildArgumentsFromActualArguments(Array* argument_names, - bool skip_push_arguments = false, - bool do_drop = false); + intptr_t* positional_argument_count); + Fragment BuildArgumentsFromActualArguments(Array* argument_names); Fragment BuildInvalidExpression(TokenPosition* position); Fragment BuildVariableGet(TokenPosition* position); diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index 6ad928be8df..c7afab66154 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -336,7 +336,7 @@ Fragment FlowGraphBuilder::InstanceCall( bool use_unchecked_entry, const CallSiteAttributesMetadata* call_site_attrs) { const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0); - ArgumentArray arguments = GetArguments(total_count); + InputsArray* arguments = GetArguments(total_count); InstanceCallInstr* call = new (Z) InstanceCallInstr(position, name, kind, arguments, type_args_len, argument_names, checked_argument_count, ic_data_array_, @@ -469,7 +469,6 @@ Fragment FlowGraphBuilder::LoadLateField(const Field& field, /* argument_count = */ 0, ICData::kStatic); } else { initialize += LoadLocal(instance); - initialize += PushArgument(); initialize += StaticCall(position, init_function, /* argument_count = */ 1, ICData::kStatic); } @@ -510,8 +509,6 @@ Fragment FlowGraphBuilder::ThrowLateInitializationError(TokenPosition position, // Call _LateInitializationError._throwNew. instructions += Constant(name); - instructions += PushArgument(); // name - instructions += StaticCall(position, throw_new, /* argument_count = */ 1, ICData::kStatic); instructions += Drop(); @@ -590,7 +587,7 @@ Fragment FlowGraphBuilder::NativeCall(const String* name, InlineBailout("kernel::FlowGraphBuilder::NativeCall"); const intptr_t num_args = function->NumParameters() + (function->IsGeneric() ? 1 : 0); - ArgumentArray arguments = GetArguments(num_args); + InputsArray* arguments = GetArguments(num_args); NativeCallInstr* call = new (Z) NativeCallInstr(name, function, FLAG_link_natives_lazily, function->end_token_pos(), arguments); @@ -665,7 +662,7 @@ Fragment FlowGraphBuilder::StaticCall(TokenPosition position, intptr_t type_args_count, bool use_unchecked_entry) { const intptr_t total_count = argument_count + (type_args_count > 0 ? 1 : 0); - ArgumentArray arguments = GetArguments(total_count); + InputsArray* arguments = GetArguments(total_count); StaticCallInstr* call = new (Z) StaticCallInstr(position, target, type_args_count, argument_names, arguments, ic_data_array_, GetNextDeoptId(), rebind_rule); @@ -695,7 +692,6 @@ Fragment FlowGraphBuilder::StringInterpolateSingle(TokenPosition position) { cls, Library::PrivateCoreLibName(Symbols::InterpolateSingle()), kTypeArgsLen, kNumberOfArguments, kNoArgumentNames)); Fragment instructions; - instructions += PushArgument(); instructions += StaticCall(position, function, /* argument_count = */ 1, ICData::kStatic); return instructions; @@ -726,20 +722,11 @@ Fragment FlowGraphBuilder::ThrowTypeError() { LocalVariable* instance = MakeTemporary(); // Call _TypeError._create constructor. - instructions += LoadLocal(instance); - instructions += PushArgument(); // this - - instructions += Constant(url); - instructions += PushArgument(); // url - - instructions += NullConstant(); - instructions += PushArgument(); // line - - instructions += IntConstant(0); - instructions += PushArgument(); // column - - instructions += Constant(H.DartSymbolPlain("Malformed type.")); - instructions += PushArgument(); // message + instructions += LoadLocal(instance); // this + instructions += Constant(url); // url + instructions += NullConstant(); // line + instructions += IntConstant(0); // column + instructions += Constant(H.DartSymbolPlain("Malformed type.")); // message instructions += StaticCall(TokenPosition::kNoSource, constructor, /* argument_count = */ 5, ICData::kStatic); @@ -762,23 +749,14 @@ Fragment FlowGraphBuilder::ThrowNoSuchMethodError() { Fragment instructions; // Call NoSuchMethodError._throwNew static function. - instructions += NullConstant(); - instructions += PushArgument(); // receiver + instructions += NullConstant(); // receiver - instructions += Constant(H.DartString("", Heap::kOld)); - instructions += PushArgument(); // memberName - - instructions += IntConstant(-1); - instructions += PushArgument(); // invocation_type - - instructions += NullConstant(); - instructions += PushArgument(); // type arguments - - instructions += NullConstant(); - instructions += PushArgument(); // arguments - - instructions += NullConstant(); - instructions += PushArgument(); // argumentNames + instructions += + Constant(H.DartString("", Heap::kOld)); // memberName + instructions += IntConstant(-1); // invocation_type + instructions += NullConstant(); // type arguments + instructions += NullConstant(); // arguments + instructions += NullConstant(); // argumentNames instructions += StaticCall(TokenPosition::kNoSource, throw_function, /* argument_count = */ 6, ICData::kStatic); @@ -832,11 +810,9 @@ Fragment FlowGraphBuilder::NativeFunctionBody(const Function& function, String& name = String::ZoneHandle(Z, function.native_name()); if (function.IsGeneric()) { body += LoadLocal(parsed_function_->RawTypeArgumentsVariable()); - body += PushArgument(); } for (intptr_t i = 0; i < function.NumParameters(); ++i) { body += LoadLocal(parsed_function_->RawParameterVariable(i)); - body += PushArgument(); } body += NativeCall(&name, &function); // We typecheck results of native calls for type safety. @@ -1096,9 +1072,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( Fragment allocate(allocate_non_growable); allocate += LoadLocal(parsed_function_->RawParameterVariable(0)); - allocate += PushArgument(); allocate += LoadLocal(parsed_function_->RawParameterVariable(1)); - allocate += PushArgument(); allocate += StaticCall(TokenPosition::kNoSource, func, 2, ICData::kStatic); allocate += StoreLocal(TokenPosition::kNoSource, @@ -1118,9 +1092,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( Fragment allocate(allocate_growable); allocate += LoadLocal(parsed_function_->RawParameterVariable(0)); - allocate += PushArgument(); allocate += IntConstant(0); - allocate += PushArgument(); allocate += StaticCall(TokenPosition::kNoSource, func, 2, ICData::kStatic); allocate += StoreLocal(TokenPosition::kNoSource, @@ -1850,7 +1822,6 @@ Fragment FlowGraphBuilder::PushExplicitParameters(const Function& function) { n = function.NumParameters(); i < n; ++i) { instructions += LoadLocal(parsed_function_->ParameterVariable(i)); - instructions += PushArgument(); } return instructions; } @@ -1913,16 +1884,13 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher( // The receiver is the first argument to noSuchMethod, and it is the first // argument passed to the dispatcher function. body += LoadLocal(parsed_function_->ParameterVariable(0)); - body += PushArgument(); // The second argument to noSuchMethod is an invocation mirror. Push the // arguments for allocating the invocation mirror. First, the name. body += Constant(String::ZoneHandle(Z, function.name())); - body += PushArgument(); // Second, the arguments descriptor. body += Constant(descriptor_array); - body += PushArgument(); // Third, an array containing the original arguments. Create it and fill // it in. @@ -1955,11 +1923,9 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher( body += LoadLocal(parsed_function_->ParameterVariable(parameter_index)); body += StoreIndexed(kArrayCid); } - body += PushArgument(); // Fourth, false indicating this is not a super NoSuchMethod. body += Constant(Bool::False()); - body += PushArgument(); const Class& mirror_class = Class::Handle(Z, Library::LookupCoreClass(Symbols::InvocationMirror())); @@ -1970,7 +1936,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher( ASSERT(!allocation_function.IsNull()); body += StaticCall(TokenPosition::kMinSource, allocation_function, /* argument_count = */ 4, ICData::kStatic); - body += PushArgument(); // For the call to noSuchMethod. const int kTypeArgsLen = 0; ArgumentsDescriptor two_arguments( @@ -2048,7 +2013,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfInvokeFieldDispatcher( LocalVariable* type_args = parsed_function_->function_type_arguments(); ASSERT(type_args != NULL); body += LoadLocal(type_args); - body += PushArgument(); } LocalVariable* closure = NULL; @@ -2060,7 +2024,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfInvokeFieldDispatcher( } else { // Invoke the getter to get the field value. body += LoadLocal(parsed_function_->ParameterVariable(0)); - body += PushArgument(); const intptr_t kTypeArgsLen = 0; const intptr_t kNumArgsChecked = 1; body += InstanceCall(TokenPosition::kMinSource, getter_name, Token::kGET, @@ -2068,13 +2031,10 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfInvokeFieldDispatcher( Function::null_function()); } - body += PushArgument(); - // Push all arguments onto the stack. intptr_t pos = 1; for (; pos < descriptor.Count(); pos++) { body += LoadLocal(parsed_function_->ParameterVariable(pos)); - body += PushArgument(); } if (is_closure_call) { @@ -2272,10 +2232,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder( } else { body += LoadLocal(parsed_function_->ParameterVariable(0)); } - body += PushArgument(); body += Constant(String::ZoneHandle(Z, function.name())); - body += PushArgument(); if (!parsed_function_->has_arg_desc_var()) { // If there is no variable for the arguments descriptor (this function's @@ -2286,10 +2244,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder( } else { body += LoadArgDescriptor(); } - body += PushArgument(); body += LoadLocal(arguments); - body += PushArgument(); if (throw_no_such_method_error) { const Function& parent = @@ -2311,7 +2267,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder( } else { body += NullConstant(); } - body += PushArgument(); // Push the number of delayed type arguments. if (function.IsClosureFunction()) { @@ -2329,7 +2284,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder( } else { body += IntConstant(0); } - body += PushArgument(); const Class& mirror_class = Class::Handle(Z, Library::LookupCoreClass(Symbols::InvocationMirror())); @@ -2340,7 +2294,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder( ASSERT(!allocation_function.IsNull()); body += StaticCall(TokenPosition::kMinSource, allocation_function, /* argument_count = */ 5, ICData::kStatic); - body += PushArgument(); // For the call to noSuchMethod. if (throw_no_such_method_error) { const Class& klass = Class::ZoneHandle( @@ -2540,7 +2493,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction( type_args_len = function.NumTypeParameters(); ASSERT(parsed_function_->function_type_arguments() != NULL); body += LoadLocal(parsed_function_->function_type_arguments()); - body += PushArgument(); } // Push receiver. @@ -2551,7 +2503,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction( body += LoadNativeField(Slot::Closure_context()); body += LoadNativeField(Slot::GetContextVariableSlotFor( thread_, *parsed_function_->receiver_var())); - body += PushArgument(); } body += PushExplicitParameters(function); @@ -2790,13 +2741,11 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfDynamicInvocationForwarder( type_args_len = function.NumTypeParameters(); ASSERT(parsed_function_->function_type_arguments() != nullptr); body += LoadLocal(parsed_function_->function_type_arguments()); - body += PushArgument(); } // Push receiver. ASSERT(function.NumImplicitParameters() == 1); body += LoadLocal(parsed_function_->receiver_var()); - body += PushArgument(); body += PushExplicitParameters(function); @@ -3049,7 +2998,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFfiCallback(const Function& function) { Push(parameter); body <<= parameter; body += FfiConvertArgumentToDart(ffi_type, arg_reps[i]); - body += PushArgument(); } // Call the target. diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc index 28365d10bc1..500a52ff1cf 100644 --- a/runtime/vm/regexp_assembler_ir.cc +++ b/runtime/vm/regexp_assembler_ir.cc @@ -28,10 +28,10 @@ TAG_(); \ } #define TAG_() \ - Print(PushArgument(Bind(new (Z) ConstantInstr(String::ZoneHandle( \ + Print(Bind(new (Z) ConstantInstr(String::ZoneHandle( \ Z, String::Concat(String::Handle(String::New("TAG: ")), \ String::Handle(String::New(__FUNCTION__)), \ - Heap::kOld)))))); + Heap::kOld))))); #define PRINT(arg) \ if (FLAG_trace_irregexp) { \ @@ -179,7 +179,7 @@ void IRRegExpMacroAssembler::GenerateEntryBlock() { TAG(); // Store string.length. - PushArgumentInstr* string_push = PushLocal(string_param_); + Value* string_push = PushLocal(string_param_); StoreLocal(string_param_length_, Bind(InstanceCall(InstanceCallDescriptor(String::ZoneHandle( @@ -188,8 +188,8 @@ void IRRegExpMacroAssembler::GenerateEntryBlock() { // Store (start_index - string.length) as the current position (since it's a // negative offset from the end of the string). - PushArgumentInstr* start_index_push = PushLocal(start_index_param_); - PushArgumentInstr* length_push = PushLocal(string_param_length_); + Value* start_index_push = PushLocal(start_index_param_); + Value* length_push = PushLocal(string_param_length_); StoreLocal(current_position_, Bind(Sub(start_index_push, length_push))); @@ -199,12 +199,10 @@ void IRRegExpMacroAssembler::GenerateEntryBlock() { ClearRegisters(0, saved_registers_count_ - 1); // Generate a local list variable to represent the backtracking stack. - PushArgumentInstr* stack_cell_push = - PushArgument(Bind(new (Z) ConstantInstr(stack_array_cell_))); + Value* stack_cell_push = Bind(new (Z) ConstantInstr(stack_array_cell_)); StoreLocal(stack_, Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), - stack_cell_push, - PushArgument(Bind(Uint64Constant(0)))))); + stack_cell_push, Bind(Uint64Constant(0))))); StoreLocal(stack_pointer_, Bind(Int64Constant(-1))); // Jump to the start block. @@ -221,9 +219,8 @@ void IRRegExpMacroAssembler::GenerateBacktrackBlock() { TypedData& offsets = TypedData::ZoneHandle( Z, TypedData::New(kTypedDataInt32ArrayCid, entries_count, Heap::kOld)); - PushArgumentInstr* block_offsets_push = - PushArgument(Bind(new (Z) ConstantInstr(offsets))); - PushArgumentInstr* block_id_push = PushArgument(Bind(PopStack())); + Value* block_offsets_push = Bind(new (Z) ConstantInstr(offsets)); + Value* block_id_push = Bind(PopStack()); Value* offset_value = Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), @@ -252,15 +249,14 @@ void IRRegExpMacroAssembler::GenerateSuccessBlock() { // Store captured offsets in the `matches` parameter. for (intptr_t i = 0; i < saved_registers_count_; i++) { - PushArgumentInstr* matches_push = PushLocal(result_); - PushArgumentInstr* index_push = PushArgument(Bind(Uint64Constant(i))); + Value* matches_push = PushLocal(result_); + Value* index_push = Bind(Uint64Constant(i)); // Convert negative offsets from the end of the string to string indices. // TODO(zerny): use positive offsets from the get-go. - PushArgumentInstr* offset_push = PushArgument(LoadRegister(i)); - PushArgumentInstr* len_push = PushLocal(string_param_length_); - PushArgumentInstr* value_push = - PushArgument(Bind(Add(offset_push, len_push))); + Value* offset_push = LoadRegister(i); + Value* len_push = PushLocal(string_param_length_); + Value* value_push = Bind(Add(offset_push, len_push)); Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), matches_push, index_push, value_push)); @@ -405,8 +401,8 @@ ConstantInstr* IRRegExpMacroAssembler::WordCharacterMapConstant() const { } ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind, - PushArgumentInstr* lhs, - PushArgumentInstr* rhs) { + Value* lhs, + Value* rhs) { Token::Kind strict_comparison = Token::kEQ_STRICT; Token::Kind intermediate_operator = Token::kILLEGAL; switch (kind) { @@ -447,25 +443,23 @@ ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind, ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind, Definition* lhs, Definition* rhs) { - PushArgumentInstr* lhs_push = PushArgument(Bind(lhs)); - PushArgumentInstr* rhs_push = PushArgument(Bind(rhs)); + Value* lhs_push = Bind(lhs); + Value* rhs_push = Bind(rhs); return Comparison(kind, lhs_push, rhs_push); } StaticCallInstr* IRRegExpMacroAssembler::StaticCall( const Function& function, ICData::RebindRule rebind_rule) const { - ZoneGrowableArray* arguments = - new (Z) ZoneGrowableArray(0); + InputsArray* arguments = new (Z) InputsArray(Z, 0); return StaticCall(function, arguments, rebind_rule); } StaticCallInstr* IRRegExpMacroAssembler::StaticCall( const Function& function, - PushArgumentInstr* arg1, + Value* arg1, ICData::RebindRule rebind_rule) const { - ZoneGrowableArray* arguments = - new (Z) ZoneGrowableArray(1); + InputsArray* arguments = new (Z) InputsArray(Z, 1); arguments->Add(arg1); return StaticCall(function, arguments, rebind_rule); @@ -473,11 +467,10 @@ StaticCallInstr* IRRegExpMacroAssembler::StaticCall( StaticCallInstr* IRRegExpMacroAssembler::StaticCall( const Function& function, - PushArgumentInstr* arg1, - PushArgumentInstr* arg2, + Value* arg1, + Value* arg2, ICData::RebindRule rebind_rule) const { - ZoneGrowableArray* arguments = - new (Z) ZoneGrowableArray(2); + InputsArray* arguments = new (Z) InputsArray(Z, 2); arguments->Add(arg1); arguments->Add(arg2); @@ -486,7 +479,7 @@ StaticCallInstr* IRRegExpMacroAssembler::StaticCall( StaticCallInstr* IRRegExpMacroAssembler::StaticCall( const Function& function, - ZoneGrowableArray* arguments, + InputsArray* arguments, ICData::RebindRule rebind_rule) const { const intptr_t kTypeArgsLen = 0; return new (Z) StaticCallInstr(TokenPosition::kNoSource, function, @@ -496,9 +489,8 @@ StaticCallInstr* IRRegExpMacroAssembler::StaticCall( InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( const InstanceCallDescriptor& desc, - PushArgumentInstr* arg1) const { - ZoneGrowableArray* arguments = - new (Z) ZoneGrowableArray(1); + Value* arg1) const { + InputsArray* arguments = new (Z) InputsArray(Z, 1); arguments->Add(arg1); return InstanceCall(desc, arguments); @@ -506,10 +498,9 @@ InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( const InstanceCallDescriptor& desc, - PushArgumentInstr* arg1, - PushArgumentInstr* arg2) const { - ZoneGrowableArray* arguments = - new (Z) ZoneGrowableArray(2); + Value* arg1, + Value* arg2) const { + InputsArray* arguments = new (Z) InputsArray(Z, 2); arguments->Add(arg1); arguments->Add(arg2); @@ -518,11 +509,10 @@ InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( const InstanceCallDescriptor& desc, - PushArgumentInstr* arg1, - PushArgumentInstr* arg2, - PushArgumentInstr* arg3) const { - ZoneGrowableArray* arguments = - new (Z) ZoneGrowableArray(3); + Value* arg1, + Value* arg2, + Value* arg3) const { + InputsArray* arguments = new (Z) InputsArray(Z, 3); arguments->Add(arg1); arguments->Add(arg2); arguments->Add(arg3); @@ -532,7 +522,7 @@ InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall( const InstanceCallDescriptor& desc, - ZoneGrowableArray* arguments) const { + InputsArray* arguments) const { const intptr_t kTypeArgsLen = 0; return new (Z) InstanceCallInstr( TokenPosition::kNoSource, desc.name, desc.token_kind, arguments, @@ -594,7 +584,6 @@ void IRRegExpMacroAssembler::AppendInstruction(Instruction* instruction) { ASSERT(current_instruction_->next() == NULL); temp_id_.Dealloc(instruction->InputCount()); - arg_id_.Dealloc(instruction->ArgumentCount()); current_instruction_->LinkTo(instruction); set_current_instruction(instruction); @@ -607,7 +596,6 @@ void IRRegExpMacroAssembler::CloseBlockWith(Instruction* instruction) { ASSERT(current_instruction_->next() == NULL); temp_id_.Dealloc(instruction->InputCount()); - arg_id_.Dealloc(instruction->ArgumentCount()); current_instruction_->LinkTo(instruction); set_current_instruction(NULL); @@ -633,24 +621,16 @@ void IRRegExpMacroAssembler::GoTo(JoinEntryInstr* to) { set_current_instruction(NULL); } -PushArgumentInstr* IRRegExpMacroAssembler::PushArgument(Value* value) { - arg_id_.Alloc(); - PushArgumentInstr* push = new (Z) PushArgumentInstr(value); - // Do *not* use Do() for push argument instructions. - AppendInstruction(push); - return push; -} - -PushArgumentInstr* IRRegExpMacroAssembler::PushLocal(LocalVariable* local) { - return PushArgument(Bind(LoadLocal(local))); +Value* IRRegExpMacroAssembler::PushLocal(LocalVariable* local) { + return Bind(LoadLocal(local)); } void IRRegExpMacroAssembler::Print(const char* str) { - Print(PushArgument(Bind(new (Z) ConstantInstr( - String::ZoneHandle(Z, String::New(str, Heap::kOld)))))); + Print(Bind(new (Z) ConstantInstr( + String::ZoneHandle(Z, String::New(str, Heap::kOld))))); } -void IRRegExpMacroAssembler::Print(PushArgumentInstr* argument) { +void IRRegExpMacroAssembler::Print(Value* argument) { const Library& lib = Library::Handle(Library::CoreLibrary()); const Function& print_fn = Function::ZoneHandle(Z, lib.LookupFunctionAllowPrivate(Symbols::print())); @@ -670,8 +650,8 @@ intptr_t IRRegExpMacroAssembler::stack_limit_slack() { void IRRegExpMacroAssembler::AdvanceCurrentPosition(intptr_t by) { TAG(); if (by != 0) { - PushArgumentInstr* cur_pos_push = PushLocal(current_position_); - PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); + Value* cur_pos_push = PushLocal(current_position_); + Value* by_push = Bind(Int64Constant(by)); Value* new_pos_value = Bind(Add(cur_pos_push, by_push)); StoreLocal(current_position_, new_pos_value); @@ -684,11 +664,11 @@ void IRRegExpMacroAssembler::AdvanceRegister(intptr_t reg, intptr_t by) { ASSERT(reg < registers_count_); if (by != 0) { - PushArgumentInstr* registers_push = PushLocal(registers_); - PushArgumentInstr* index_push = PushRegisterIndex(reg); - PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); - PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); - PushArgumentInstr* value_push = PushArgument(Bind(Add(reg_push, by_push))); + Value* registers_push = PushLocal(registers_); + Value* index_push = PushRegisterIndex(reg); + Value* reg_push = LoadRegister(reg); + Value* by_push = Bind(Int64Constant(by)); + Value* value_push = Bind(Add(reg_push, by_push)); StoreRegister(registers_push, index_push, value_push); } } @@ -714,7 +694,7 @@ void IRRegExpMacroAssembler::BindBlock(BlockLabel* label) { set_current_instruction(label->block()); // Print the id of the current block if tracing. - PRINT(PushArgument(Bind(Uint64Constant(label->block()->block_id())))); + PRINT(Bind(Uint64Constant(label->block()->block_id()))); } intptr_t IRRegExpMacroAssembler::GetNextLocalIndex() { @@ -723,32 +703,32 @@ intptr_t IRRegExpMacroAssembler::GetNextLocalIndex() { } Value* IRRegExpMacroAssembler::LoadRegister(intptr_t index) { - PushArgumentInstr* registers_push = PushLocal(registers_); - PushArgumentInstr* index_push = PushRegisterIndex(index); + Value* registers_push = PushLocal(registers_); + Value* index_push = PushRegisterIndex(index); return Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), registers_push, index_push)); } void IRRegExpMacroAssembler::StoreRegister(intptr_t index, intptr_t value) { - PushArgumentInstr* registers_push = PushLocal(registers_); - PushArgumentInstr* index_push = PushRegisterIndex(index); - PushArgumentInstr* value_push = PushArgument(Bind(Uint64Constant(value))); + Value* registers_push = PushLocal(registers_); + Value* index_push = PushRegisterIndex(index); + Value* value_push = Bind(Uint64Constant(value)); StoreRegister(registers_push, index_push, value_push); } -void IRRegExpMacroAssembler::StoreRegister(PushArgumentInstr* registers, - PushArgumentInstr* index, - PushArgumentInstr* value) { +void IRRegExpMacroAssembler::StoreRegister(Value* registers, + Value* index, + Value* value) { TAG(); Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), registers, index, value)); } -PushArgumentInstr* IRRegExpMacroAssembler::PushRegisterIndex(intptr_t index) { +Value* IRRegExpMacroAssembler::PushRegisterIndex(intptr_t index) { if (registers_count_ <= index) { registers_count_ = index + 1; } - return PushArgument(Bind(Uint64Constant(index))); + return Bind(Uint64Constant(index)); } void IRRegExpMacroAssembler::CheckCharacter(uint32_t c, BlockLabel* on_equal) { @@ -785,12 +765,11 @@ void IRRegExpMacroAssembler::CheckNotAtStart(intptr_t cp_offset, TAG(); // Are we at the start of the input, i.e. is (offset == string_length * -1)? - auto offset_def = - PushArgument(Bind(Add(PushLocal(current_position_), - PushArgument(Bind(Int64Constant(cp_offset)))))); - auto neg_len_def = PushArgument( + auto neg_len_def = Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE), - PushLocal(string_param_length_)))); + PushLocal(string_param_length_))); + auto offset_def = + Bind(Add(PushLocal(current_position_), Bind(Int64Constant(cp_offset)))); BranchOrBacktrack(Comparison(kNE, neg_len_def, offset_def), on_not_at_start); } @@ -829,8 +808,8 @@ void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( BlockLabel fallthrough; - PushArgumentInstr* end_push = PushArgument(LoadRegister(start_reg + 1)); - PushArgumentInstr* start_push = PushArgument(LoadRegister(start_reg)); + Value* end_push = LoadRegister(start_reg + 1); + Value* start_push = LoadRegister(start_reg); StoreLocal(capture_length_, Bind(Sub(end_push, start_push))); // The length of a capture should not be negative. This can only happen @@ -848,8 +827,8 @@ void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( Comparison(kEQ, LoadLocal(capture_length_), Uint64Constant(0)), &fallthrough); - PushArgumentInstr* pos_push = nullptr; - PushArgumentInstr* len_push = nullptr; + Value* pos_push = nullptr; + Value* len_push = nullptr; if (!read_backward) { // Check that there are sufficient characters left in the input. @@ -880,7 +859,7 @@ void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( StoreLocal(match_start_index_, Bind(Sub(pos_push, len_push))); } - pos_push = PushArgument(LoadRegister(start_reg)); + pos_push = LoadRegister(start_reg); len_push = PushLocal(string_param_length_); StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push))); @@ -902,8 +881,8 @@ void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( &loop_increment); // Mismatch, try case-insensitive match (converting letters to lower-case). - PushArgumentInstr* match_char_push = PushLocal(char_in_match_); - PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(0x20))); + Value* match_char_push = PushLocal(char_in_match_); + Value* mask_push = Bind(Uint64Constant(0x20)); StoreLocal( char_in_match_, Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_OR), @@ -935,8 +914,8 @@ void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( // Also convert capture character. BindBlock(&convert_capture); - PushArgumentInstr* capture_char_push = PushLocal(char_in_capture_); - mask_push = PushArgument(Bind(Uint64Constant(0x20))); + Value* capture_char_push = PushLocal(char_in_capture_); + mask_push = Bind(Uint64Constant(0x20)); StoreLocal( char_in_capture_, Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_OR), @@ -949,12 +928,12 @@ void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( BindBlock(&loop_increment); // Increment indexes into capture and match strings. - PushArgumentInstr* index_push = PushLocal(capture_start_index_); - PushArgumentInstr* inc_push = PushArgument(Bind(Uint64Constant(1))); + Value* index_push = PushLocal(capture_start_index_); + Value* inc_push = Bind(Uint64Constant(1)); StoreLocal(capture_start_index_, Bind(Add(index_push, inc_push))); index_push = PushLocal(match_start_index_); - inc_push = PushArgument(Bind(Uint64Constant(1))); + inc_push = Bind(Uint64Constant(1)); StoreLocal(match_start_index_, Bind(Add(index_push, inc_push))); // Compare to end of match, and loop if not done. @@ -994,7 +973,7 @@ void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( StoreLocal(current_position_, Bind(Sub(pos_push, len_push))); } else { // Move current character position to position after match. - PushArgumentInstr* match_end_push = PushLocal(match_end_index_); + Value* match_end_push = PushLocal(match_end_index_); len_push = PushLocal(string_param_length_); StoreLocal(current_position_, Bind(Sub(match_end_push, len_push))); } @@ -1012,8 +991,8 @@ void IRRegExpMacroAssembler::CheckNotBackReference(intptr_t start_reg, BlockLabel success; // Find length of back-referenced capture. - PushArgumentInstr* end_push = PushArgument(LoadRegister(start_reg + 1)); - PushArgumentInstr* start_push = PushArgument(LoadRegister(start_reg)); + Value* end_push = LoadRegister(start_reg + 1); + Value* start_push = LoadRegister(start_reg); StoreLocal(capture_length_, Bind(Sub(end_push, start_push))); // Fail on partial or illegal capture (start of capture after end of capture). @@ -1026,8 +1005,8 @@ void IRRegExpMacroAssembler::CheckNotBackReference(intptr_t start_reg, Comparison(kEQ, LoadLocal(capture_length_), Uint64Constant(0)), &fallthrough); - PushArgumentInstr* pos_push = nullptr; - PushArgumentInstr* len_push = nullptr; + Value* pos_push = nullptr; + Value* len_push = nullptr; if (!read_backward) { // Check that there are sufficient characters left in the input. @@ -1059,7 +1038,7 @@ void IRRegExpMacroAssembler::CheckNotBackReference(intptr_t start_reg, StoreLocal(match_start_index_, Bind(Sub(pos_push, len_push))); } - pos_push = PushArgument(LoadRegister(start_reg)); + pos_push = LoadRegister(start_reg); len_push = PushLocal(string_param_length_); StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push))); @@ -1078,12 +1057,12 @@ void IRRegExpMacroAssembler::CheckNotBackReference(intptr_t start_reg, on_no_match); // Increment indexes into capture and match strings. - PushArgumentInstr* index_push = PushLocal(capture_start_index_); - PushArgumentInstr* inc_push = PushArgument(Bind(Uint64Constant(1))); + Value* index_push = PushLocal(capture_start_index_); + Value* inc_push = Bind(Uint64Constant(1)); StoreLocal(capture_start_index_, Bind(Add(index_push, inc_push))); index_push = PushLocal(match_start_index_); - inc_push = PushArgument(Bind(Uint64Constant(1))); + inc_push = Bind(Uint64Constant(1)); StoreLocal(match_start_index_, Bind(Add(index_push, inc_push))); // Check if we have reached end of match area. @@ -1100,7 +1079,7 @@ void IRRegExpMacroAssembler::CheckNotBackReference(intptr_t start_reg, StoreLocal(current_position_, Bind(Sub(pos_push, len_push))); } else { // Move current character position to position after match. - PushArgumentInstr* match_end_push = PushLocal(match_end_index_); + Value* match_end_push = PushLocal(match_end_index_); len_push = PushLocal(string_param_length_); StoreLocal(current_position_, Bind(Sub(match_end_push, len_push))); } @@ -1122,12 +1101,12 @@ void IRRegExpMacroAssembler::CheckCharacterAfterAnd(uint32_t c, TAG(); Definition* actual_def = LoadLocal(current_character_); - Definition* expected_def = Uint64Constant(c); - PushArgumentInstr* actual_push = PushArgument(Bind(actual_def)); - PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask))); + Value* actual_push = Bind(actual_def); + Value* mask_push = Bind(Uint64Constant(mask)); actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND), actual_push, mask_push); + Definition* expected_def = Uint64Constant(c); BranchOrBacktrack(Comparison(kEQ, actual_def, expected_def), on_equal); } @@ -1139,12 +1118,12 @@ void IRRegExpMacroAssembler::CheckNotCharacterAfterAnd( TAG(); Definition* actual_def = LoadLocal(current_character_); - Definition* expected_def = Uint64Constant(c); - PushArgumentInstr* actual_push = PushArgument(Bind(actual_def)); - PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask))); + Value* actual_push = Bind(actual_def); + Value* mask_push = Bind(Uint64Constant(mask)); actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND), actual_push, mask_push); + Definition* expected_def = Uint64Constant(c); BranchOrBacktrack(Comparison(kNE, actual_def, expected_def), on_not_equal); } @@ -1158,15 +1137,15 @@ void IRRegExpMacroAssembler::CheckNotCharacterAfterMinusAnd( ASSERT(minus < Utf16::kMaxCodeUnit); // NOLINT Definition* actual_def = LoadLocal(current_character_); - Definition* expected_def = Uint64Constant(c); - PushArgumentInstr* actual_push = PushArgument(Bind(actual_def)); - PushArgumentInstr* minus_push = PushArgument(Bind(Uint64Constant(minus))); + Value* actual_push = Bind(actual_def); + Value* minus_push = Bind(Uint64Constant(minus)); - actual_push = PushArgument(Bind(Sub(actual_push, minus_push))); - PushArgumentInstr* mask_push = PushArgument(Bind(Uint64Constant(mask))); + actual_push = Bind(Sub(actual_push, minus_push)); + Value* mask_push = Bind(Uint64Constant(mask)); actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND), actual_push, mask_push); + Definition* expected_def = Uint64Constant(c); BranchOrBacktrack(Comparison(kNE, actual_def, expected_def), on_not_equal); } @@ -1212,16 +1191,14 @@ void IRRegExpMacroAssembler::CheckBitInTable(const TypedData& table, BlockLabel* on_bit_set) { TAG(); - PushArgumentInstr* table_push = - PushArgument(Bind(new (Z) ConstantInstr(table))); - PushArgumentInstr* index_push = PushLocal(current_character_); + Value* table_push = Bind(new (Z) ConstantInstr(table)); + Value* index_push = PushLocal(current_character_); if (mode_ != ASCII || kTableMask != Symbols::kMaxOneCharCodeSymbol) { - PushArgumentInstr* mask_push = - PushArgument(Bind(Uint64Constant(kTableSize - 1))); - index_push = PushArgument( + Value* mask_push = Bind(Uint64Constant(kTableSize - 1)); + index_push = Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND), - index_push, mask_push))); + index_push, mask_push)); } Definition* byte_def = InstanceCall( @@ -1295,9 +1272,8 @@ bool IRRegExpMacroAssembler::CheckSpecialCharacterClass( on_no_match); } - PushArgumentInstr* table_push = - PushArgument(Bind(WordCharacterMapConstant())); - PushArgumentInstr* index_push = PushLocal(current_character_); + Value* table_push = Bind(WordCharacterMapConstant()); + Value* index_push = PushLocal(current_character_); Definition* byte_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), @@ -1319,9 +1295,8 @@ bool IRRegExpMacroAssembler::CheckSpecialCharacterClass( // TODO(zerny): Refactor to use CheckBitInTable if possible. - PushArgumentInstr* table_push = - PushArgument(Bind(WordCharacterMapConstant())); - PushArgumentInstr* index_push = PushLocal(current_character_); + Value* table_push = Bind(WordCharacterMapConstant()); + Value* index_push = PushLocal(current_character_); Definition* byte_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), @@ -1380,8 +1355,8 @@ void IRRegExpMacroAssembler::IfRegisterGE(intptr_t reg, intptr_t comparand, BlockLabel* if_ge) { TAG(); - PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); - PushArgumentInstr* pos = PushArgument(Bind(Int64Constant(comparand))); + Value* reg_push = LoadRegister(reg); + Value* pos = Bind(Int64Constant(comparand)); BranchOrBacktrack(Comparison(kGTE, reg_push, pos), if_ge); } @@ -1389,15 +1364,15 @@ void IRRegExpMacroAssembler::IfRegisterLT(intptr_t reg, intptr_t comparand, BlockLabel* if_lt) { TAG(); - PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); - PushArgumentInstr* pos = PushArgument(Bind(Int64Constant(comparand))); + Value* reg_push = LoadRegister(reg); + Value* pos = Bind(Int64Constant(comparand)); BranchOrBacktrack(Comparison(kLT, reg_push, pos), if_lt); } void IRRegExpMacroAssembler::IfRegisterEqPos(intptr_t reg, BlockLabel* if_eq) { TAG(); - PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); - PushArgumentInstr* pos = PushArgument(Bind(LoadLocal(current_position_))); + Value* reg_push = LoadRegister(reg); + Value* pos = Bind(LoadLocal(current_position_)); BranchOrBacktrack(Comparison(kEQ, reg_push, pos), if_eq); } @@ -1430,37 +1405,37 @@ void IRRegExpMacroAssembler::PopCurrentPosition() { void IRRegExpMacroAssembler::PopRegister(intptr_t reg) { TAG(); ASSERT(reg < registers_count_); - PushArgumentInstr* registers_push = PushLocal(registers_); - PushArgumentInstr* index_push = PushRegisterIndex(reg); - PushArgumentInstr* pop_push = PushArgument(Bind(PopStack())); + Value* registers_push = PushLocal(registers_); + Value* index_push = PushRegisterIndex(reg); + Value* pop_push = Bind(PopStack()); StoreRegister(registers_push, index_push, pop_push); } void IRRegExpMacroAssembler::PushStack(Definition* definition) { - PushArgumentInstr* stack_push = PushLocal(stack_); - PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); - StoreLocal(stack_pointer_, Bind(Add(stack_pointer_push, - PushArgument(Bind(Uint64Constant(1)))))); + Value* stack_push = PushLocal(stack_); + Value* stack_pointer_push = PushLocal(stack_pointer_); + StoreLocal(stack_pointer_, + Bind(Add(stack_pointer_push, Bind(Uint64Constant(1))))); stack_pointer_push = PushLocal(stack_pointer_); // TODO(zerny): bind value and push could break stack discipline. - PushArgumentInstr* value_push = PushArgument(Bind(definition)); + Value* value_push = Bind(definition); Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), stack_push, stack_pointer_push, value_push)); } Definition* IRRegExpMacroAssembler::PopStack() { - PushArgumentInstr* stack_push = PushLocal(stack_); - PushArgumentInstr* stack_pointer_push1 = PushLocal(stack_pointer_); - PushArgumentInstr* stack_pointer_push2 = PushLocal(stack_pointer_); - StoreLocal(stack_pointer_, Bind(Sub(stack_pointer_push2, - PushArgument(Bind(Uint64Constant(1)))))); + Value* stack_push = PushLocal(stack_); + Value* stack_pointer_push1 = PushLocal(stack_pointer_); + Value* stack_pointer_push2 = PushLocal(stack_pointer_); + StoreLocal(stack_pointer_, + Bind(Sub(stack_pointer_push2, Bind(Uint64Constant(1))))); return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), stack_push, stack_pointer_push1); } Definition* IRRegExpMacroAssembler::PeekStack() { - PushArgumentInstr* stack_push = PushLocal(stack_); - PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); + Value* stack_push = PushLocal(stack_); + Value* stack_pointer_push = PushLocal(stack_pointer_); return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), stack_push, stack_pointer_push); } @@ -1490,13 +1465,13 @@ void IRRegExpMacroAssembler::PushCurrentPosition() { void IRRegExpMacroAssembler::PushRegister(intptr_t reg) { TAG(); // TODO(zerny): Refactor PushStack so it can be reused here. - PushArgumentInstr* stack_push = PushLocal(stack_); - PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); - StoreLocal(stack_pointer_, Bind(Add(stack_pointer_push, - PushArgument(Bind(Uint64Constant(1)))))); + Value* stack_push = PushLocal(stack_); + Value* stack_pointer_push = PushLocal(stack_pointer_); + StoreLocal(stack_pointer_, + Bind(Add(stack_pointer_push, Bind(Uint64Constant(1))))); stack_pointer_push = PushLocal(stack_pointer_); // TODO(zerny): bind value and push could break stack discipline. - PushArgumentInstr* value_push = PushArgument(LoadRegister(reg)); + Value* value_push = LoadRegister(reg); Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), stack_push, stack_pointer_push, value_push)); CheckStackLimit(); @@ -1508,14 +1483,14 @@ void IRRegExpMacroAssembler::PushRegister(intptr_t reg) { // stack will be grown. void IRRegExpMacroAssembler::CheckStackLimit() { TAG(); - PushArgumentInstr* stack_push = PushLocal(stack_); - PushArgumentInstr* length_push = PushArgument( + Value* stack_push = PushLocal(stack_); + Value* length_push = Bind(InstanceCall(InstanceCallDescriptor(String::ZoneHandle( Field::GetterSymbol(Symbols::Length()))), - stack_push))); - PushArgumentInstr* capacity_push = PushArgument(Bind(Sub( - length_push, PushArgument(Bind(Uint64Constant(stack_limit_slack())))))); - PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); + stack_push)); + Value* capacity_push = + Bind(Sub(length_push, Bind(Uint64Constant(stack_limit_slack())))); + Value* stack_pointer_push = PushLocal(stack_pointer_); BranchInstr* branch = new (Z) BranchInstr( Comparison(kGT, capacity_push, stack_pointer_push), GetNextDeoptId()); CloseBlockWith(branch); @@ -1544,10 +1519,9 @@ void IRRegExpMacroAssembler::GrowStack() { // as a constant but :stack is a local variable and its value might be // comming from OSR or deoptimization. This means we should never use // stack_array_cell in the body of the :matcher to reload the :stack. - PushArgumentInstr* stack_cell_push = - PushArgument(Bind(new (Z) ConstantInstr(stack_array_cell_))); - PushArgumentInstr* index_push = PushArgument(Bind(Uint64Constant(0))); - PushArgumentInstr* stack_push = PushLocal(stack_); + Value* stack_cell_push = Bind(new (Z) ConstantInstr(stack_array_cell_)); + Value* index_push = Bind(Uint64Constant(0)); + Value* stack_push = PushLocal(stack_); Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), stack_cell_push, index_push, stack_push)); } @@ -1603,11 +1577,11 @@ void IRRegExpMacroAssembler::WriteCurrentPositionToRegister( intptr_t cp_offset) { TAG(); - PushArgumentInstr* registers_push = PushLocal(registers_); - PushArgumentInstr* index_push = PushRegisterIndex(reg); - PushArgumentInstr* pos_push = PushLocal(current_position_); - PushArgumentInstr* off_push = PushArgument(Bind(Int64Constant(cp_offset))); - PushArgumentInstr* neg_off_push = PushArgument(Bind(Add(pos_push, off_push))); + Value* registers_push = PushLocal(registers_); + Value* index_push = PushRegisterIndex(reg); + Value* pos_push = PushLocal(current_position_); + Value* off_push = Bind(Int64Constant(cp_offset)); + Value* neg_off_push = Bind(Add(pos_push, off_push)); // Push the negative offset; these are converted to positive string positions // within the success block. StoreRegister(registers_push, index_push, neg_off_push); @@ -1623,12 +1597,11 @@ void IRRegExpMacroAssembler::ClearRegisters(intptr_t reg_from, // (-1 - string length), the offset of -1 from the end of the string. for (intptr_t reg = reg_from; reg <= reg_to; reg++) { - PushArgumentInstr* registers_push = PushLocal(registers_); - PushArgumentInstr* index_push = PushRegisterIndex(reg); - PushArgumentInstr* minus_one_push = PushArgument(Bind(Int64Constant(-1))); - PushArgumentInstr* length_push = PushLocal(string_param_length_); - PushArgumentInstr* value_push = - PushArgument(Bind(Sub(minus_one_push, length_push))); + Value* registers_push = PushLocal(registers_); + Value* index_push = PushRegisterIndex(reg); + Value* minus_one_push = Bind(Int64Constant(-1)); + Value* length_push = PushLocal(string_param_length_); + Value* value_push = Bind(Sub(minus_one_push, length_push)); StoreRegister(registers_push, index_push, value_push); } } @@ -1636,9 +1609,9 @@ void IRRegExpMacroAssembler::ClearRegisters(intptr_t reg_from, void IRRegExpMacroAssembler::WriteStackPointerToRegister(intptr_t reg) { TAG(); - PushArgumentInstr* registers_push = PushLocal(registers_); - PushArgumentInstr* index_push = PushRegisterIndex(reg); - PushArgumentInstr* tip_push = PushLocal(stack_pointer_); + Value* registers_push = PushLocal(registers_); + Value* index_push = PushRegisterIndex(reg); + Value* tip_push = PushLocal(stack_pointer_); StoreRegister(registers_push, index_push, tip_push); } @@ -1659,8 +1632,8 @@ void IRRegExpMacroAssembler::CheckPosition(intptr_t cp_offset, // We need to see if there's enough characters left in the string to go // back cp_offset characters, so get the normalized position and then // make sure that (normalized_position >= -cp_offset). - PushArgumentInstr* pos_push = PushLocal(current_position_); - PushArgumentInstr* len_push = PushLocal(string_param_length_); + Value* pos_push = PushLocal(current_position_); + Value* len_push = PushLocal(string_param_length_); BranchOrBacktrack( Comparison(kLT, Add(pos_push, len_push), Uint64Constant(-cp_offset)), on_outside_input); @@ -1734,13 +1707,11 @@ void IRRegExpMacroAssembler::CheckPreemption(bool is_backtrack) { : CheckStackOverflowInstr::kOsrOnly)); } -Definition* IRRegExpMacroAssembler::Add(PushArgumentInstr* lhs, - PushArgumentInstr* rhs) { +Definition* IRRegExpMacroAssembler::Add(Value* lhs, Value* rhs) { return InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), lhs, rhs); } -Definition* IRRegExpMacroAssembler::Sub(PushArgumentInstr* lhs, - PushArgumentInstr* rhs) { +Definition* IRRegExpMacroAssembler::Sub(Value* lhs, Value* rhs) { return InstanceCall(InstanceCallDescriptor::FromToken(Token::kSUB), lhs, rhs); } @@ -1760,11 +1731,10 @@ void IRRegExpMacroAssembler::LoadCurrentCharacterUnchecked( // Calculate the addressed string index as: // cp_offset + current_position_ + string_param_length_ // TODO(zerny): Avoid generating 'add' instance-calls here. - PushArgumentInstr* off_arg = PushArgument(Bind(Int64Constant(cp_offset))); - PushArgumentInstr* pos_arg = PushArgument(BindLoadLocal(*current_position_)); - PushArgumentInstr* off_pos_arg = PushArgument(Bind(Add(off_arg, pos_arg))); - PushArgumentInstr* len_arg = - PushArgument(BindLoadLocal(*string_param_length_)); + Value* off_arg = Bind(Int64Constant(cp_offset)); + Value* pos_arg = BindLoadLocal(*current_position_); + Value* off_pos_arg = Bind(Add(off_arg, pos_arg)); + Value* len_arg = BindLoadLocal(*string_param_length_); // Index is stored in a temporary local so that we can later load it safely. StoreLocal(index_temp_, Bind(Add(off_pos_arg, len_arg))); diff --git a/runtime/vm/regexp_assembler_ir.h b/runtime/vm/regexp_assembler_ir.h index d8c222a568f..fb92f1b16a1 100644 --- a/runtime/vm/regexp_assembler_ir.h +++ b/runtime/vm/regexp_assembler_ir.h @@ -228,37 +228,34 @@ class IRRegExpMacroAssembler : public RegExpMacroAssembler { // Used by generated RegExp code. ConstantInstr* WordCharacterMapConstant() const; - ComparisonInstr* Comparison(ComparisonKind kind, - PushArgumentInstr* lhs, - PushArgumentInstr* rhs); + ComparisonInstr* Comparison(ComparisonKind kind, Value* lhs, Value* rhs); ComparisonInstr* Comparison(ComparisonKind kind, Definition* lhs, Definition* rhs); InstanceCallInstr* InstanceCall(const InstanceCallDescriptor& desc, - PushArgumentInstr* arg1) const; + Value* arg1) const; InstanceCallInstr* InstanceCall(const InstanceCallDescriptor& desc, - PushArgumentInstr* arg1, - PushArgumentInstr* arg2) const; + Value* arg1, + Value* arg2) const; InstanceCallInstr* InstanceCall(const InstanceCallDescriptor& desc, - PushArgumentInstr* arg1, - PushArgumentInstr* arg2, - PushArgumentInstr* arg3) const; - InstanceCallInstr* InstanceCall( - const InstanceCallDescriptor& desc, - ZoneGrowableArray* arguments) const; + Value* arg1, + Value* arg2, + Value* arg3) const; + InstanceCallInstr* InstanceCall(const InstanceCallDescriptor& desc, + InputsArray* arguments) const; StaticCallInstr* StaticCall(const Function& function, ICData::RebindRule rebind_rule) const; StaticCallInstr* StaticCall(const Function& function, - PushArgumentInstr* arg1, + Value* arg1, ICData::RebindRule rebind_rule) const; StaticCallInstr* StaticCall(const Function& function, - PushArgumentInstr* arg1, - PushArgumentInstr* arg2, + Value* arg1, + Value* arg2, ICData::RebindRule rebind_rule) const; StaticCallInstr* StaticCall(const Function& function, - ZoneGrowableArray* arguments, + InputsArray* arguments, ICData::RebindRule rebind_rule) const; // Creates a new block consisting simply of a goto to dst. @@ -266,21 +263,18 @@ class IRRegExpMacroAssembler : public RegExpMacroAssembler { IndirectEntryInstr* IndirectWithJoinGoto(JoinEntryInstr* dst); // Adds, respectively subtracts lhs and rhs and returns the result. - Definition* Add(PushArgumentInstr* lhs, PushArgumentInstr* rhs); - Definition* Sub(PushArgumentInstr* lhs, PushArgumentInstr* rhs); + Definition* Add(Value* lhs, Value* rhs); + Definition* Sub(Value* lhs, Value* rhs); LoadLocalInstr* LoadLocal(LocalVariable* local) const; void StoreLocal(LocalVariable* local, Value* value); - PushArgumentInstr* PushArgument(Value* value); - PushArgumentInstr* PushLocal(LocalVariable* local); + Value* PushLocal(LocalVariable* local); - PushArgumentInstr* PushRegisterIndex(intptr_t reg); + Value* PushRegisterIndex(intptr_t reg); Value* LoadRegister(intptr_t reg); void StoreRegister(intptr_t reg, intptr_t value); - void StoreRegister(PushArgumentInstr* registers, - PushArgumentInstr* index, - PushArgumentInstr* value); + void StoreRegister(Value* registers, Value* index, Value* value); // Load a number of characters at the given offset from the // current position, into the current-character register. @@ -347,7 +341,7 @@ class IRRegExpMacroAssembler : public RegExpMacroAssembler { void GrowStack(); // Prints the specified argument. Used for debugging. - void Print(PushArgumentInstr* argument); + void Print(Value* argument); // A utility class tracking ids of various objects such as blocks, temps, etc. class IdAllocator : public ValueObject { @@ -442,7 +436,6 @@ class IRRegExpMacroAssembler : public RegExpMacroAssembler { IdAllocator block_id_; IdAllocator temp_id_; - IdAllocator arg_id_; IdAllocator local_id_; IdAllocator indirect_id_; };