Skip to content

Commit

Permalink
[deoptimizer] Add construct create/invoke stub translate state
Browse files Browse the repository at this point in the history
These are, for the moment, the same % pc_offset to the
ConstructStub builtin.

Follow up CLs will differentiate both frames.

Bug: v8:14192

Change-Id: I70236f10ad8ecb08d4e6749428afe4e6479bb3c5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4694645
Reviewed-by: Darius Mercadier <dmercadier@chromium.org>
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/main@{#89010}
  • Loading branch information
victorgomes authored and V8 LUCI CQ committed Jul 18, 2023
1 parent fcb81f9 commit f4556ab
Show file tree
Hide file tree
Showing 24 changed files with 205 additions and 168 deletions.
10 changes: 7 additions & 3 deletions src/compiler/backend/code-generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
#include "src/compiler/globals.h"
#include "src/compiler/linkage.h"
#include "src/compiler/pipeline.h"
#include "src/deoptimizer/translated-state.h"
#include "src/diagnostics/eh-frame.h"
#include "src/execution/frames.h"
#include "src/logging/counters.h"
#include "src/logging/log.h"
#include "src/objects/smi.h"
#include "src/utils/address-map.h"
#include "src/utils/utils.h"

namespace v8 {
namespace internal {
Expand Down Expand Up @@ -1099,9 +1101,11 @@ void CodeGenerator::BuildTranslationForFrameStateDescriptor(
case FrameStateType::kInlinedExtraArguments:
translations_.BeginInlinedExtraArguments(shared_info_id, height);
break;
case FrameStateType::kConstructStub:
DCHECK(bailout_id.IsValidForConstructStub());
translations_.BeginConstructStubFrame(bailout_id, shared_info_id, height);
case FrameStateType::kConstructCreateStub:
translations_.BeginConstructCreateStubFrame(shared_info_id, height);
break;
case FrameStateType::kConstructInvokeStub:
translations_.BeginConstructInvokeStubFrame(shared_info_id, height);
break;
case FrameStateType::kBuiltinContinuation: {
translations_.BeginBuiltinContinuationFrame(bailout_id, shared_info_id,
Expand Down
7 changes: 5 additions & 2 deletions src/compiler/backend/instruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "src/codegen/register-configuration.h"
#include "src/codegen/source-position.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/frame-states.h"
#include "src/compiler/graph.h"
#include "src/compiler/node.h"
#include "src/compiler/schedule.h"
Expand Down Expand Up @@ -1146,7 +1147,8 @@ size_t GetConservativeFrameSizeInBytes(FrameStateType type,
#if V8_ENABLE_WEBASSEMBLY
case FrameStateType::kWasmInlinedIntoJS:
#endif
case FrameStateType::kConstructStub: {
case FrameStateType::kConstructCreateStub:
case FrameStateType::kConstructInvokeStub: {
auto info = ConstructStubFrameInfo::Conservative(
static_cast<int>(parameters_count));
return info.frame_size_in_bytes();
Expand Down Expand Up @@ -1217,7 +1219,8 @@ size_t FrameStateDescriptor::GetHeight() const {
// a receiver or context).
return parameters_count();
case FrameStateType::kInlinedExtraArguments:
case FrameStateType::kConstructStub:
case FrameStateType::kConstructCreateStub:
case FrameStateType::kConstructInvokeStub:
case FrameStateType::kJavaScriptBuiltinContinuation:
case FrameStateType::kJavaScriptBuiltinContinuationWithCatch:
// JS linkage. The parameters count
Expand Down
11 changes: 6 additions & 5 deletions src/compiler/backend/instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1466,7 +1466,8 @@ class FrameStateDescriptor : public ZoneObject {
// inlined wasm functions?
type_ == FrameStateType::kWasmInlinedIntoJS ||
#endif // V8_ENABLE_WEBASSEMBLY
type_ == FrameStateType::kConstructStub;
type_ == FrameStateType::kConstructCreateStub ||
type_ == FrameStateType::kConstructInvokeStub;
}

// The frame height on the stack, in number of slots, as serialized into a
Expand Down Expand Up @@ -1680,10 +1681,10 @@ class V8_EXPORT_PRIVATE InstructionBlock final
const RpoNumber loop_header_;
const RpoNumber loop_end_;
RpoNumber dominator_;
int32_t code_start_; // start index of arch-specific code.
int32_t code_end_ = -1; // end index of arch-specific code.
const bool deferred_ : 1; // Block contains deferred code.
bool handler_ : 1; // Block is a handler entry point.
int32_t code_start_; // start index of arch-specific code.
int32_t code_end_ = -1; // end index of arch-specific code.
const bool deferred_ : 1; // Block contains deferred code.
bool handler_ : 1; // Block is a handler entry point.
bool switch_target_ : 1;
bool code_target_alignment_ : 1; // insert code target alignment before this
// block
Expand Down
13 changes: 5 additions & 8 deletions src/compiler/frame-states.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,27 @@ size_t hash_value(OutputFrameStateCombine const& sc) {
return base::hash_value(sc.parameter_);
}


std::ostream& operator<<(std::ostream& os, OutputFrameStateCombine const& sc) {
if (sc.parameter_ == OutputFrameStateCombine::kInvalidIndex)
return os << "Ignore";
return os << "PokeAt(" << sc.parameter_ << ")";
}


bool operator==(FrameStateInfo const& lhs, FrameStateInfo const& rhs) {
return lhs.type() == rhs.type() && lhs.bailout_id() == rhs.bailout_id() &&
lhs.state_combine() == rhs.state_combine() &&
lhs.function_info() == rhs.function_info();
}


bool operator!=(FrameStateInfo const& lhs, FrameStateInfo const& rhs) {
return !(lhs == rhs);
}


size_t hash_value(FrameStateInfo const& info) {
return base::hash_combine(static_cast<int>(info.type()), info.bailout_id(),
info.state_combine());
}


std::ostream& operator<<(std::ostream& os, FrameStateType type) {
switch (type) {
case FrameStateType::kUnoptimizedFunction:
Expand All @@ -58,8 +53,11 @@ std::ostream& operator<<(std::ostream& os, FrameStateType type) {
case FrameStateType::kInlinedExtraArguments:
os << "INLINED_EXTRA_ARGUMENTS";
break;
case FrameStateType::kConstructStub:
os << "CONSTRUCT_STUB";
case FrameStateType::kConstructCreateStub:
os << "CONSTRUCT_CREATE_STUB";
break;
case FrameStateType::kConstructInvokeStub:
os << "CONSTRUCT_INVOKE_STUB";
break;
case FrameStateType::kBuiltinContinuation:
os << "BUILTIN_CONTINUATION_FRAME";
Expand All @@ -82,7 +80,6 @@ std::ostream& operator<<(std::ostream& os, FrameStateType type) {
return os;
}


std::ostream& operator<<(std::ostream& os, FrameStateInfo const& info) {
os << info.type() << ", " << info.bailout_id() << ", "
<< info.state_combine();
Expand Down
14 changes: 8 additions & 6 deletions src/compiler/frame-states.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,16 @@ class OutputFrameStateCombine {
size_t const parameter_;
};


// The type of stack frame that a FrameState node represents.
enum class FrameStateType {
kUnoptimizedFunction, // Represents an UnoptimizedFrame.
kInlinedExtraArguments, // Represents inlined extra arguments.
kConstructStub, // Represents a ConstructStubFrame.
kBuiltinContinuation, // Represents a continuation to a stub.
#if V8_ENABLE_WEBASSEMBLY // ↓ WebAssembly only
kUnoptimizedFunction, // Represents an UnoptimizedFrame.
kInlinedExtraArguments, // Represents inlined extra arguments.
kConstructCreateStub, // Represents a frame created before creating a new
// object in the construct stub.
kConstructInvokeStub, // Represents a frame created before invoking the
// constructor in the construct stub.
kBuiltinContinuation, // Represents a continuation to a stub.
#if V8_ENABLE_WEBASSEMBLY // ↓ WebAssembly only
kJSToWasmBuiltinContinuation, // Represents a lazy deopt continuation for a
// JS to Wasm call.
kWasmInlinedIntoJS, // Represents a Wasm function inlined into a
Expand Down
22 changes: 11 additions & 11 deletions src/compiler/js-call-reducer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "src/objects/js-function.h"
#include "src/objects/objects-inl.h"
#include "src/objects/ordered-hash-table.h"
#include "src/utils/utils.h"

#ifdef V8_INTL_SUPPORT
#include "src/objects/intl-objects.h"
Expand Down Expand Up @@ -2317,15 +2318,14 @@ struct PromiseCtorFrameStateParams {
// but probably not worth the effort.
FrameState CreateArtificialFrameState(
Node* node, Node* outer_frame_state, int parameter_count,
BytecodeOffset bailout_id, FrameStateType frame_state_type,
SharedFunctionInfoRef shared, Node* context, CommonOperatorBuilder* common,
Graph* graph) {
FrameStateType frame_state_type, SharedFunctionInfoRef shared,
Node* context, CommonOperatorBuilder* common, Graph* graph) {
const FrameStateFunctionInfo* state_info =
common->CreateFrameStateFunctionInfo(
frame_state_type, parameter_count + 1, 0, shared.object());

const Operator* op = common->FrameState(
bailout_id, OutputFrameStateCombine::Ignore(), state_info);
BytecodeOffset::None(), OutputFrameStateCombine::Ignore(), state_info);
const Operator* op0 = common->StateValues(0, SparseInputMask::Dense());
Node* node0 = graph->NewNode(op0);

Expand All @@ -2352,10 +2352,10 @@ FrameState PromiseConstructorFrameState(
Graph* graph) {
DCHECK_EQ(1,
params.shared.internal_formal_parameter_count_without_receiver());
return CreateArtificialFrameState(
params.node_ptr, params.outer_frame_state, 1,
BytecodeOffset::ConstructStubInvoke(), FrameStateType::kConstructStub,
params.shared, params.context, common, graph);
return CreateArtificialFrameState(params.node_ptr, params.outer_frame_state,
1, FrameStateType::kConstructInvokeStub,
params.shared, params.context, common,
graph);
}

FrameState PromiseConstructorLazyFrameState(
Expand Down Expand Up @@ -7399,9 +7399,9 @@ Reduction JSCallReducer::ReduceTypedArrayConstructor(

// Insert a construct stub frame into the chain of frame states. This will
// reconstruct the proper frame when deoptimizing within the constructor.
frame_state = CreateArtificialFrameState(
node, frame_state, arity, BytecodeOffset::ConstructStubInvoke(),
FrameStateType::kConstructStub, shared, context, common(), graph());
frame_state = CreateArtificialFrameState(node, frame_state, arity,
FrameStateType::kConstructInvokeStub,
shared, context, common(), graph());

// This continuation just returns the newly created JSTypedArray. We
// pass the_hole as the receiver, just like the builtin construct stub
Expand Down
16 changes: 7 additions & 9 deletions src/compiler/js-inlining.cc
Original file line number Diff line number Diff line change
Expand Up @@ -245,16 +245,16 @@ Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context,

FrameState JSInliner::CreateArtificialFrameState(
Node* node, FrameState outer_frame_state, int parameter_count,
BytecodeOffset bailout_id, FrameStateType frame_state_type,
SharedFunctionInfoRef shared, Node* context, Node* callee) {
FrameStateType frame_state_type, SharedFunctionInfoRef shared,
Node* context, Node* callee) {
const int parameter_count_with_receiver =
parameter_count + JSCallOrConstructNode::kReceiverOrNewTargetInputCount;
const FrameStateFunctionInfo* state_info =
common()->CreateFrameStateFunctionInfo(
frame_state_type, parameter_count_with_receiver, 0, shared.object());

const Operator* op = common()->FrameState(
bailout_id, OutputFrameStateCombine::Ignore(), state_info);
BytecodeOffset::None(), OutputFrameStateCombine::Ignore(), state_info);
const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
Node* node0 = graph()->NewNode(op0);

Expand Down Expand Up @@ -588,7 +588,7 @@ void JSInliner::InlineWasmFunction(Node* call, Node* inlinee_start,
// We do not have a proper callee JSFunction object.
Node* callee = jsgraph()->UndefinedConstant();
Node* frame_state_inside = CreateArtificialFrameState(
call, FrameState{frame_state}, argument_count, BytecodeOffset::None(),
call, FrameState{frame_state}, argument_count,
FrameStateType::kWasmInlinedIntoJS, shared_fct_info, context, callee);
Node* check_point = graph()->NewNode(common()->Checkpoint(),
frame_state_inside, effect, control);
Expand Down Expand Up @@ -838,8 +838,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
} else {
frame_state_inside = CreateArtificialFrameState(
node, frame_state, n.ArgumentCount(),
BytecodeOffset::ConstructStubCreate(),
FrameStateType::kConstructStub, *shared_info, caller_context);
FrameStateType::kConstructCreateStub, *shared_info, caller_context);
}
Node* create =
graph()->NewNode(javascript()->Create(), call.target(), new_target,
Expand Down Expand Up @@ -894,8 +893,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
// reconstruct the proper frame when deoptimizing within the constructor.
frame_state = CreateArtificialFrameState(
node, frame_state, n.ArgumentCount(),
BytecodeOffset::ConstructStubInvoke(), FrameStateType::kConstructStub,
*shared_info, caller_context);
FrameStateType::kConstructInvokeStub, *shared_info, caller_context);
}

// Insert a JSConvertReceiver node for sloppy callees. Note that the context
Expand Down Expand Up @@ -924,7 +922,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
DCHECK_EQ(parameter_count, start.FormalParameterCountWithoutReceiver());
if (call.argument_count() != parameter_count) {
frame_state = CreateArtificialFrameState(
node, frame_state, call.argument_count(), BytecodeOffset::None(),
node, frame_state, call.argument_count(),
FrameStateType::kInlinedExtraArguments, *shared_info);
}

Expand Down
5 changes: 2 additions & 3 deletions src/compiler/js-inlining.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,8 @@ class JSInliner final : public AdvancedReducer {

FrameState CreateArtificialFrameState(
Node* node, FrameState outer_frame_state, int parameter_count,
BytecodeOffset bailout_id, FrameStateType frame_state_type,
SharedFunctionInfoRef shared, Node* context = nullptr,
Node* callee = nullptr);
FrameStateType frame_state_type, SharedFunctionInfoRef shared,
Node* context = nullptr, Node* callee = nullptr);

Reduction InlineCall(Node* call, Node* new_target, Node* context,
Node* frame_state, StartNode start, Node* end,
Expand Down
29 changes: 14 additions & 15 deletions src/deoptimizer/deoptimizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "src/debug/debug.h"
#include "src/deoptimizer/deoptimized-frame-info.h"
#include "src/deoptimizer/materialized-object-store.h"
#include "src/deoptimizer/translated-state.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate.h"
#include "src/execution/pointer-authentication.h"
Expand All @@ -23,6 +24,7 @@
#include "src/objects/js-function-inl.h"
#include "src/objects/oddball.h"
#include "src/snapshot/embedded/embedded-data.h"
#include "src/utils/utils.h"

#if V8_ENABLE_WEBASSEMBLY
#include "src/wasm/wasm-linkage.h"
Expand Down Expand Up @@ -843,7 +845,8 @@ void Deoptimizer::DoComputeOutputFrames() {
case TranslatedFrame::kInlinedExtraArguments:
DoComputeInlinedExtraArguments(translated_frame, frame_index);
break;
case TranslatedFrame::kConstructStub:
case TranslatedFrame::kConstructCreateStub:
case TranslatedFrame::kConstructInvokeStub:
DoComputeConstructStubFrame(translated_frame, frame_index);
break;
case TranslatedFrame::kBuiltinContinuation:
Expand Down Expand Up @@ -1355,10 +1358,13 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
// the topmost one). So it could only be the DeoptimizeKind::kLazy case.
CHECK(!is_topmost || deopt_kind_ == DeoptimizeKind::kLazy);

bool is_create_stub =
(translated_frame->kind() == TranslatedFrame::kConstructCreateStub);
DCHECK(is_create_stub ||
(translated_frame->kind() == TranslatedFrame::kConstructInvokeStub));

Builtins* builtins = isolate_->builtins();
Code construct_stub = builtins->code(Builtin::kJSConstructStubGeneric);
BytecodeOffset bytecode_offset = translated_frame->bytecode_offset();

const int parameters_count = translated_frame->height();
ConstructStubFrameInfo frame_info =
ConstructStubFrameInfo::Precise(parameters_count, is_topmost);
Expand All @@ -1367,11 +1373,9 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
TranslatedFrame::iterator function_iterator = value_iterator++;
if (verbose_tracing_enabled()) {
PrintF(trace_scope()->file(),
" translating construct stub => bytecode_offset=%d (%s), "
"variable_frame_size=%d, frame_size=%d\n",
bytecode_offset.ToInt(),
bytecode_offset == BytecodeOffset::ConstructStubCreate() ? "create"
: "invoke",
" translating construct %s stub => variable_frame_size=%d, "
"frame_size=%d\n",
is_create_stub ? "create" : "invoke",
frame_info.frame_size_in_bytes_without_fixed(), output_frame_size);
}

Expand Down Expand Up @@ -1448,12 +1452,8 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,

frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");

CHECK(bytecode_offset == BytecodeOffset::ConstructStubCreate() ||
bytecode_offset == BytecodeOffset::ConstructStubInvoke());
const char* debug_hint =
bytecode_offset == BytecodeOffset::ConstructStubCreate()
? "new target\n"
: "allocated receiver\n";
is_create_stub ? "new target\n" : "allocated receiver\n";
frame_writer.PushTranslatedValue(receiver_iterator, debug_hint);

if (is_topmost) {
Expand All @@ -1470,10 +1470,9 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
CHECK_EQ(0u, frame_writer.top_offset());

// Compute this frame's PC.
DCHECK(bytecode_offset.IsValidForConstructStub());
Address start = construct_stub.instruction_start();
const int pc_offset =
bytecode_offset == BytecodeOffset::ConstructStubCreate()
is_create_stub
? isolate_->heap()->construct_stub_create_deopt_pc_offset().value()
: isolate_->heap()->construct_stub_invoke_deopt_pc_offset().value();
intptr_t pc_value = static_cast<intptr_t>(start + pc_offset);
Expand Down
Loading

0 comments on commit f4556ab

Please sign in to comment.