[compiler] Remove turboprop-specific opcodes

TierUpCheck and UpdateInterruptBudget were only used by Turboprop
(likewise feedback_cell_node).

Bug: v8:12552
Change-Id: Ic73d44a5734e183bc1a2eda58cdf85163220e4d9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3463954
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79116}
This commit is contained in:
Jakob Gruber 2022-02-15 15:17:55 +01:00 committed by V8 LUCI CQ
parent d7418d416c
commit 3f03910c11
13 changed files with 1 additions and 272 deletions

View File

@ -7,8 +7,6 @@ namespace internal {
namespace runtime {
extern runtime GetTemplateObject(implicit context: Context)(
TemplateObjectDescription, SharedFunctionInfo, Smi): JSAny;
extern runtime BytecodeBudgetInterruptFromCode(implicit context: Context)(
FeedbackCell): JSAny;
}
builtin GetTemplateObject(
@ -40,13 +38,6 @@ builtin GetTemplateObject(
}
}
builtin BytecodeBudgetInterruptFromCode(implicit context: Context)(
feedbackCell: FeedbackCell): Object {
// The runtime call is wrapped by a builtin since the calling sequence in
// generated code is shorter for builtins than for runtime calls.
tail runtime::BytecodeBudgetInterruptFromCode(feedbackCell);
}
extern transitioning builtin ForInFilter(implicit context: Context)(
JSAny, HeapObject): JSAny;
extern enum ForInFeedback extends uint31 { kAny, ...}

View File

@ -90,13 +90,6 @@ class BytecodeGraphBuilder {
return feedback_vector_node_;
}
void CreateFeedbackCellNode();
Node* feedback_cell_node() const {
DCHECK(CodeKindCanTierUp(code_kind()));
DCHECK_NOT_NULL(feedback_cell_node_);
return feedback_cell_node_;
}
// Same as above for the feedback vector node.
void CreateNativeContextNode();
Node* native_context_node() const {
@ -106,12 +99,7 @@ class BytecodeGraphBuilder {
Node* BuildLoadFeedbackCell(int index);
// Checks the optimization marker and potentially triggers compilation or
// installs the finished code object.
// Only relevant for specific code kinds (see CodeKindCanTierUp).
void MaybeBuildTierUpCheck();
// Builder for loading the a native context field.
// Builder for loading a native context field.
Node* BuildLoadNativeContextField(int index);
// Helper function for creating a feedback source containing type feedback
@ -342,8 +330,6 @@ class BytecodeGraphBuilder {
void BuildJumpIfNotHole();
void BuildJumpIfJSReceiver();
void BuildUpdateInterruptBudget(int delta);
void BuildSwitchOnSmi(Node* condition);
void BuildSwitchOnGeneratorState(
const ZoneVector<ResumeJumpTarget>& resume_jump_targets,
@ -505,7 +491,6 @@ class BytecodeGraphBuilder {
Node** input_buffer_;
const CodeKind code_kind_;
Node* feedback_cell_node_;
Node* feedback_vector_node_;
Node* native_context_node_;
@ -1081,7 +1066,6 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
input_buffer_size_(0),
input_buffer_(nullptr),
code_kind_(code_kind),
feedback_cell_node_(nullptr),
feedback_vector_node_(nullptr),
native_context_node_(nullptr),
needs_eager_checkpoint_(true),
@ -1121,14 +1105,6 @@ Node* BytecodeGraphBuilder::GetParameter(int parameter_index,
return cached_parameters_[index];
}
void BytecodeGraphBuilder::CreateFeedbackCellNode() {
DCHECK_NULL(feedback_cell_node_);
// Only used by tier-up logic; for code that doesn't tier-up, we can skip
// this.
if (!CodeKindCanTierUp(code_kind())) return;
feedback_cell_node_ = jsgraph()->Constant(feedback_cell_);
}
void BytecodeGraphBuilder::CreateFeedbackVectorNode() {
DCHECK_NULL(feedback_vector_node_);
feedback_vector_node_ = jsgraph()->Constant(feedback_vector());
@ -1143,25 +1119,6 @@ void BytecodeGraphBuilder::CreateNativeContextNode() {
native_context_node_ = jsgraph()->Constant(native_context());
}
void BytecodeGraphBuilder::MaybeBuildTierUpCheck() {
// For OSR we don't tier up, so we don't need to build this check. Also
// tiering up currently tail calls to IET which tail calls aren't supported
// with OSR. See AdjustStackPointerForTailCall.
if (!CodeKindCanTierUp(code_kind()) || skip_tierup_check()) return;
int parameter_count = bytecode_array().parameter_count();
Node* target = GetFunctionClosure();
Node* new_target = GetParameter(
Linkage::GetJSCallNewTargetParamIndex(parameter_count), "%new.target");
Node* argc = GetParameter(
Linkage::GetJSCallArgCountParamIndex(parameter_count), "%argc");
DCHECK_EQ(environment()->Context()->opcode(), IrOpcode::kParameter);
Node* context = environment()->Context();
NewNode(simplified()->TierUpCheck(), feedback_vector_node(), target,
new_target, argc, context);
}
Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
Node* result = NewNode(javascript()->LoadContext(0, index, true));
NodeProperties::ReplaceContextInput(result, native_context_node());
@ -1192,9 +1149,7 @@ void BytecodeGraphBuilder::CreateGraph() {
graph()->start());
set_environment(&env);
CreateFeedbackCellNode();
CreateFeedbackVectorNode();
MaybeBuildTierUpCheck();
CreateNativeContextNode();
VisitBytecodes();
@ -3568,9 +3523,6 @@ void BytecodeGraphBuilder::VisitSetPendingMessage() {
void BytecodeGraphBuilder::BuildReturn(const BytecodeLivenessState* liveness) {
BuildLoopExitsForFunctionExit(liveness);
// Note: Negated offset since a return acts like a backwards jump, and should
// decrement the budget.
BuildUpdateInterruptBudget(-bytecode_iterator().current_offset());
Node* pop_node = jsgraph()->ZeroConstant();
Node* control =
NewNode(common()->Return(), pop_node, environment()->LookupAccumulator());
@ -3986,7 +3938,6 @@ void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit(
}
void BytecodeGraphBuilder::BuildJump() {
BuildUpdateInterruptBudget(bytecode_iterator().GetRelativeJumpTargetOffset());
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
}
@ -3995,8 +3946,6 @@ void BytecodeGraphBuilder::BuildJumpIf(Node* condition) {
{
SubEnvironment sub_environment(this);
NewIfTrue();
BuildUpdateInterruptBudget(
bytecode_iterator().GetRelativeJumpTargetOffset());
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
}
NewIfFalse();
@ -4007,8 +3956,6 @@ void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) {
{
SubEnvironment sub_environment(this);
NewIfFalse();
BuildUpdateInterruptBudget(
bytecode_iterator().GetRelativeJumpTargetOffset());
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
}
NewIfTrue();
@ -4033,8 +3980,6 @@ void BytecodeGraphBuilder::BuildJumpIfFalse() {
{
SubEnvironment sub_environment(this);
NewIfFalse();
BuildUpdateInterruptBudget(
bytecode_iterator().GetRelativeJumpTargetOffset());
environment()->BindAccumulator(jsgraph()->FalseConstant());
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
}
@ -4048,8 +3993,6 @@ void BytecodeGraphBuilder::BuildJumpIfTrue() {
SubEnvironment sub_environment(this);
NewIfTrue();
environment()->BindAccumulator(jsgraph()->TrueConstant());
BuildUpdateInterruptBudget(
bytecode_iterator().GetRelativeJumpTargetOffset());
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
}
NewIfFalse();
@ -4081,16 +4024,6 @@ void BytecodeGraphBuilder::BuildJumpIfJSReceiver() {
BuildJumpIf(condition);
}
void BytecodeGraphBuilder::BuildUpdateInterruptBudget(int delta) {
if (!CodeKindCanTierUp(code_kind())) return;
// Keep uses of this in sync with Ignition's UpdateInterruptBudget.
int delta_with_current_bytecode =
delta - bytecode_iterator().current_bytecode_size();
NewNode(simplified()->UpdateInterruptBudget(delta_with_current_bytecode),
feedback_cell_node());
}
JSTypeHintLowering::LoweringResult
BytecodeGraphBuilder::TryBuildSimplifiedUnaryOp(const Operator* op,
Node* operand,

View File

@ -184,8 +184,6 @@ class EffectControlLinearizer {
void LowerCheckEqualsInternalizedString(Node* node, Node* frame_state);
void LowerCheckEqualsSymbol(Node* node, Node* frame_state);
Node* LowerTypeOf(Node* node);
void LowerTierUpCheck(Node* node);
void LowerUpdateInterruptBudget(Node* node);
Node* LowerToBoolean(Node* node);
Node* LowerPlainPrimitiveToNumber(Node* node);
Node* LowerPlainPrimitiveToWord32(Node* node);
@ -1169,12 +1167,6 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kTypeOf:
result = LowerTypeOf(node);
break;
case IrOpcode::kTierUpCheck:
LowerTierUpCheck(node);
break;
case IrOpcode::kUpdateInterruptBudget:
LowerUpdateInterruptBudget(node);
break;
case IrOpcode::kNewDoubleElements:
result = LowerNewDoubleElements(node);
break;
@ -3597,85 +3589,6 @@ Node* EffectControlLinearizer::LowerTypeOf(Node* node) {
__ NoContextConstant());
}
void EffectControlLinearizer::LowerTierUpCheck(Node* node) {
TierUpCheckNode n(node);
TNode<FeedbackVector> vector = n.feedback_vector();
Node* optimization_state =
__ LoadField(AccessBuilder::ForFeedbackVectorFlags(), vector);
// TODO(jgruber): The branch introduces a sequence of spills before the
// branch (and restores at `fallthrough`) that are completely unnecessary
// since the IfFalse continuation ends in a tail call. Investigate how to
// avoid these and fix it.
auto fallthrough = __ MakeLabel();
auto has_optimized_code_or_marker = __ MakeDeferredLabel();
__ BranchWithHint(
__ Word32Equal(
__ Word32And(optimization_state,
__ Uint32Constant(
FeedbackVector::
kHasOptimizedCodeOrCompileOptimizedMarkerMask)),
__ Int32Constant(0)),
&fallthrough, &has_optimized_code_or_marker, BranchHint::kTrue);
__ Bind(&has_optimized_code_or_marker);
// The optimization marker field contains a non-trivial value, and some
// action has to be taken. For example, perhaps tier-up has been requested
// and we need to kick off a compilation job; or optimized code is available
// and should be tail-called.
//
// Currently we delegate these tasks to the InterpreterEntryTrampoline.
// TODO(jgruber,v8:8888): Consider a dedicated builtin instead.
TNode<HeapObject> code =
__ HeapConstant(BUILTIN_CODE(isolate(), InterpreterEntryTrampoline));
JSTrampolineDescriptor descriptor;
CallDescriptor::Flags flags = CallDescriptor::kFixedTargetRegister |
CallDescriptor::kIsTailCallForTierUp;
auto call_descriptor = Linkage::GetStubCallDescriptor(
graph()->zone(), descriptor, descriptor.GetStackParameterCount(), flags,
Operator::kNoProperties);
Node* nodes[] = {code, n.target(), n.new_target(), n.input_count(),
n.context(), __ effect(), __ control()};
#ifdef DEBUG
static constexpr int kCodeContextEffectControl = 4;
DCHECK_EQ(arraysize(nodes),
descriptor.GetParameterCount() + kCodeContextEffectControl);
#endif // DEBUG
__ TailCall(call_descriptor, arraysize(nodes), nodes);
__ Bind(&fallthrough);
}
void EffectControlLinearizer::LowerUpdateInterruptBudget(Node* node) {
UpdateInterruptBudgetNode n(node);
TNode<FeedbackCell> feedback_cell = n.feedback_cell();
TNode<Int32T> budget = __ LoadField<Int32T>(
AccessBuilder::ForFeedbackCellInterruptBudget(), feedback_cell);
Node* new_budget = __ Int32Add(budget, __ Int32Constant(n.delta()));
__ StoreField(AccessBuilder::ForFeedbackCellInterruptBudget(), feedback_cell,
new_budget);
if (n.delta() < 0) {
auto next = __ MakeLabel();
auto if_budget_exhausted = __ MakeDeferredLabel();
__ Branch(__ Int32LessThan(new_budget, __ Int32Constant(0)),
&if_budget_exhausted, &next);
__ Bind(&if_budget_exhausted);
CallBuiltin(Builtin::kBytecodeBudgetInterruptFromCode,
node->op()->properties(), feedback_cell);
__ Goto(&next);
__ Bind(&next);
}
}
Node* EffectControlLinearizer::LowerToBoolean(Node* node) {
Node* obj = node->InputAt(0);
Callable const callable =

View File

@ -488,14 +488,12 @@
V(StringToLowerCaseIntl) \
V(StringToNumber) \
V(StringToUpperCaseIntl) \
V(TierUpCheck) \
V(ToBoolean) \
V(TransitionAndStoreElement) \
V(TransitionAndStoreNonNumberElement) \
V(TransitionAndStoreNumberElement) \
V(TransitionElementsKind) \
V(TypeOf) \
V(UpdateInterruptBudget) \
V(VerifyType)
#define SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(V) \

View File

@ -3074,22 +3074,6 @@ class RepresentationSelector {
return VisitUnop<T>(node, UseInfo::AnyTagged(),
MachineRepresentation::kTaggedPointer);
}
case IrOpcode::kTierUpCheck: {
ProcessInput<T>(node, 0, UseInfo::AnyTagged());
ProcessInput<T>(node, 1, UseInfo::AnyTagged());
ProcessInput<T>(node, 2, UseInfo::AnyTagged());
ProcessInput<T>(node, 3, UseInfo::TruncatingWord32());
ProcessInput<T>(node, 4, UseInfo::AnyTagged());
ProcessRemainingInputs<T>(node, 5);
SetOutput<T>(node, MachineRepresentation::kNone);
return;
}
case IrOpcode::kUpdateInterruptBudget: {
ProcessInput<T>(node, 0, UseInfo::AnyTagged());
ProcessRemainingInputs<T>(node, 1);
SetOutput<T>(node, MachineRepresentation::kNone);
return;
}
case IrOpcode::kNewConsString: {
ProcessInput<T>(node, 0, UseInfo::TruncatingWord32()); // length
ProcessInput<T>(node, 1, UseInfo::AnyTagged()); // first

View File

@ -1320,18 +1320,6 @@ const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntAsUintN(
SpeculativeBigIntAsNParameters(bits, feedback));
}
const Operator* SimplifiedOperatorBuilder::UpdateInterruptBudget(int delta) {
return zone()->New<Operator1<int>>(
IrOpcode::kUpdateInterruptBudget, Operator::kNoThrow | Operator::kNoDeopt,
"UpdateInterruptBudget", 1, 1, 1, 0, 1, 0, delta);
}
const Operator* SimplifiedOperatorBuilder::TierUpCheck() {
return zone()->New<Operator>(IrOpcode::kTierUpCheck,
Operator::kNoThrow | Operator::kNoDeopt,
"TierUpCheck", 5, 1, 1, 0, 1, 0);
}
const Operator* SimplifiedOperatorBuilder::AssertType(Type type) {
DCHECK(type.CanBeAsserted());
return zone()->New<Operator1<Type>>(IrOpcode::kAssertType,

View File

@ -855,20 +855,6 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* TypeOf();
// Adds the given delta to the current feedback vector's interrupt budget,
// and calls the runtime profiler in case the budget is exhausted. A note on
// the delta parameter: the interrupt budget mechanism originates in the
// interpreter and thus still refers to 'bytecodes' even though we are
// generating native code. The interrupt budget essentially corresponds to
// the number of bytecodes we can execute before calling the profiler. The
// delta parameter represents the executed bytecodes since the last update.
const Operator* UpdateInterruptBudget(int delta);
// Takes the current feedback vector as input 0, and generates a check of the
// vector's marker. Depending on the marker's value, we either do nothing,
// trigger optimized compilation, or install a finished code object.
const Operator* TierUpCheck();
const Operator* ToBoolean();
const Operator* StringConcat();
@ -1231,37 +1217,6 @@ class FastApiCallNode final : public SimplifiedNodeWrapperBase {
}
};
class TierUpCheckNode final : public SimplifiedNodeWrapperBase {
public:
explicit constexpr TierUpCheckNode(Node* node)
: SimplifiedNodeWrapperBase(node) {
DCHECK_EQ(IrOpcode::kTierUpCheck, node->opcode());
}
#define INPUTS(V) \
V(FeedbackVector, feedback_vector, 0, FeedbackVector) \
V(Target, target, 1, JSReceiver) \
V(NewTarget, new_target, 2, Object) \
V(InputCount, input_count, 3, UntaggedT) \
V(Context, context, 4, Context)
INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};
class UpdateInterruptBudgetNode final : public SimplifiedNodeWrapperBase {
public:
explicit constexpr UpdateInterruptBudgetNode(Node* node)
: SimplifiedNodeWrapperBase(node) {
DCHECK_EQ(IrOpcode::kUpdateInterruptBudget, node->opcode());
}
int delta() const { return OpParameter<int>(node()->op()); }
#define INPUTS(V) V(FeedbackCell, feedback_cell, 0, FeedbackCell)
INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};
#undef DEFINE_INPUT_ACCESSORS
} // namespace compiler

View File

@ -1215,9 +1215,6 @@ Type Typer::Visitor::TypeTypeOf(Node* node) {
return Type::InternalizedString();
}
Type Typer::Visitor::TypeTierUpCheck(Node* node) { UNREACHABLE(); }
Type Typer::Visitor::TypeUpdateInterruptBudget(Node* node) { UNREACHABLE(); }
// JS conversion operators.
Type Typer::Visitor::TypeToBoolean(Node* node) {

View File

@ -774,11 +774,6 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
case IrOpcode::kTypeOf:
CheckTypeIs(node, Type::InternalizedString());
break;
case IrOpcode::kTierUpCheck:
case IrOpcode::kUpdateInterruptBudget:
CheckValueInputIs(node, 0, Type::Any());
CheckNotTyped(node);
break;
case IrOpcode::kJSGetSuperConstructor:
// We don't check the input for Type::Function because this_function can
// be context-allocated.

View File

@ -271,11 +271,5 @@ void TieringManager::OnInterruptTickFromBytecode() {
OnInterruptTick(it.frame());
}
void TieringManager::OnInterruptTickFromCode() {
JavaScriptFrameIterator it(isolate_);
DCHECK(it.frame()->is_optimized());
OnInterruptTick(it.frame());
}
} // namespace internal
} // namespace v8

View File

@ -25,7 +25,6 @@ class TieringManager {
explicit TieringManager(Isolate* isolate) : isolate_(isolate) {}
void OnInterruptTickFromBytecode();
void OnInterruptTickFromCode();
void NotifyICChanged() { any_ic_changed_ = true; }

View File

@ -413,23 +413,6 @@ RUNTIME_FUNCTION(Runtime_BytecodeBudgetInterruptFromBytecode) {
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_BytecodeBudgetInterruptFromCode) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(FeedbackCell, feedback_cell, 0);
// TODO(leszeks): Consider checking stack interrupts here, and removing
// those checks for code that can have budget interrupts.
DCHECK(feedback_cell->value().IsFeedbackVector());
FeedbackVector::SetInterruptBudget(*feedback_cell);
SealHandleScope shs(isolate);
isolate->tiering_manager()->OnInterruptTickFromCode();
return ReadOnlyRoots(isolate).undefined_value();
}
namespace {
#if V8_ENABLE_WEBASSEMBLY

View File

@ -222,7 +222,6 @@ namespace internal {
F(IncrementUseCounter, 1, 1) \
F(BytecodeBudgetInterruptFromBytecode, 1, 1) \
F(BytecodeBudgetInterruptWithStackCheckFromBytecode, 1, 1) \
F(BytecodeBudgetInterruptFromCode, 1, 1) \
F(NewError, 2, 1) \
F(NewReferenceError, 2, 1) \
F(NewSyntaxError, 2, 1) \