Commit 1e258045 authored by ishell@chromium.org's avatar ishell@chromium.org Committed by V8 LUCI CQ

[ext-code-space] Remove Code <-> CodeT roundtrips in deoptimizer

Bug: v8:11880
Change-Id: Ic2dcf5f540fdd1c6c138d9535033b57d22afb1b6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3825885Reviewed-by: 's avatarJakob Linke <jgruber@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82393}
parent bd0c7cb6
......@@ -182,9 +182,9 @@ Code Deoptimizer::FindDeoptimizingCode(Address addr) {
NativeContext native_context = function_.native_context();
Object element = native_context.DeoptimizedCodeListHead();
while (!element.IsUndefined(isolate)) {
Code code = FromCodeT(CodeT::cast(element));
CodeT code = CodeT::cast(element);
CHECK(CodeKindCanDeoptimize(code.kind()));
if (code.contains(isolate, addr)) return code;
if (code.contains(isolate, addr)) return FromCodeT(code);
element = code.next_code_link();
}
}
......@@ -245,7 +245,8 @@ DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
namespace {
class ActivationsFinder : public ThreadVisitor {
public:
explicit ActivationsFinder(std::set<Code>* codes, Code topmost_optimized_code,
explicit ActivationsFinder(std::set<CodeT>* codes,
CodeT topmost_optimized_code,
bool safe_to_deopt_topmost_optimized_code)
: codes_(codes) {
#ifdef DEBUG
......@@ -260,7 +261,7 @@ class ActivationsFinder : public ThreadVisitor {
void VisitThread(Isolate* isolate, ThreadLocalTop* top) override {
for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
if (it.frame()->is_optimized()) {
Code code = it.frame()->LookupCode();
CodeT code = it.frame()->LookupCodeT().ToCodeT();
if (CodeKindCanDeoptimize(code.kind()) &&
code.marked_for_deoptimization()) {
codes_->erase(code);
......@@ -289,10 +290,10 @@ class ActivationsFinder : public ThreadVisitor {
}
private:
std::set<Code>* codes_;
std::set<CodeT>* codes_;
#ifdef DEBUG
Code topmost_;
CodeT topmost_;
bool safe_to_deopt_;
#endif
};
......@@ -305,7 +306,7 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(NativeContext native_context) {
DisallowGarbageCollection no_gc;
Isolate* isolate = native_context.GetIsolate();
Code topmost_optimized_code;
CodeT topmost_optimized_code;
bool safe_to_deopt_topmost_optimized_code = false;
#ifdef DEBUG
// Make sure all activations of optimized code can deopt at their current PC.
......@@ -314,7 +315,7 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(NativeContext native_context) {
for (StackFrameIterator it(isolate, isolate->thread_local_top()); !it.done();
it.Advance()) {
if (it.frame()->is_optimized()) {
Code code = it.frame()->LookupCode();
CodeT code = it.frame()->LookupCodeT().ToCodeT();
JSFunction function =
static_cast<OptimizedFrame*>(it.frame())->function();
TraceFoundActivation(isolate, function);
......@@ -343,14 +344,14 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(NativeContext native_context) {
// We will use this set to mark those Code objects that are marked for
// deoptimization and have not been found in stack frames.
std::set<Code> codes;
std::set<CodeT> codes;
// Move marked code from the optimized code list to the deoptimized code list.
// Walk over all optimized code objects in this native context.
Code prev;
CodeT prev;
Object element = native_context.OptimizedCodeListHead();
while (!element.IsUndefined(isolate)) {
Code code = FromCodeT(CodeT::cast(element));
CodeT code = CodeT::cast(element);
CHECK(CodeKindCanDeoptimize(code.kind()));
Object next = code.next_code_link();
......@@ -370,7 +371,7 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(NativeContext native_context) {
// Move the code to the _deoptimized_ code list.
code.set_next_code_link(native_context.DeoptimizedCodeListHead());
native_context.SetDeoptimizedCodeListHead(ToCodeT(code));
native_context.SetDeoptimizedCodeListHead(code);
} else {
// Not marked; preserve this element.
prev = code;
......@@ -390,8 +391,8 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(NativeContext native_context) {
// If there's no activation of a code in any stack then we can remove its
// deoptimization data. We do this to ensure that code objects that are
// unlinked don't transitively keep objects alive unnecessarily.
for (Code code : codes) {
isolate->heap()->InvalidateCodeDeoptimizationData(code);
for (CodeT code : codes) {
isolate->heap()->InvalidateCodeDeoptimizationData(FromCodeT(code));
}
}
......@@ -438,13 +439,13 @@ void Deoptimizer::MarkAllCodeForContext(NativeContext native_context) {
}
}
void Deoptimizer::DeoptimizeFunction(JSFunction function, Code code) {
void Deoptimizer::DeoptimizeFunction(JSFunction function, CodeT code) {
Isolate* isolate = function.GetIsolate();
RCS_SCOPE(isolate, RuntimeCallCounterId::kDeoptimizeCode);
TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
TRACE_EVENT0("v8", "V8.DeoptimizeCode");
function.ResetIfCodeFlushed();
if (code.is_null()) code = FromCodeT(function.code());
if (code.is_null()) code = function.code();
if (CodeKindCanDeoptimize(code.kind())) {
// Mark the code for deoptimization and unlink any functions that also
......@@ -1020,8 +1021,8 @@ void Deoptimizer::DoComputeUnoptimizedFrame(TranslatedFrame* translated_frame,
const bool deopt_to_baseline =
shared.HasBaselineCode() && FLAG_deopt_to_baseline;
const bool restart_frame = goto_catch_handler && is_restart_frame();
Code dispatch_builtin = FromCodeT(builtins->code(
DispatchBuiltinFor(deopt_to_baseline, advance_bc, restart_frame)));
CodeT dispatch_builtin = builtins->code(
DispatchBuiltinFor(deopt_to_baseline, advance_bc, restart_frame));
if (verbose_tracing_enabled()) {
PrintF(trace_scope()->file(), " translating %s frame ",
......@@ -1341,8 +1342,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
CHECK(!is_topmost || deopt_kind_ == DeoptimizeKind::kLazy);
Builtins* builtins = isolate_->builtins();
Code construct_stub =
FromCodeT(builtins->code(Builtin::kJSConstructStubGeneric));
CodeT construct_stub = builtins->code(Builtin::kJSConstructStubGeneric);
BytecodeOffset bytecode_offset = translated_frame->bytecode_offset();
const int parameters_count = translated_frame->height();
......
......@@ -76,7 +76,7 @@ class Deoptimizer : public Malloced {
// again and any activations of the optimized code will get deoptimized when
// execution returns. If {code} is specified then the given code is targeted
// instead of the function code (e.g. OSR code not installed on function).
static void DeoptimizeFunction(JSFunction function, Code code = Code());
static void DeoptimizeFunction(JSFunction function, CodeT code = {});
// Deoptimize all code in the given isolate.
V8_EXPORT_PRIVATE static void DeoptimizeAll(Isolate* isolate);
......
......@@ -2095,7 +2095,8 @@ void TranslatedState::StoreMaterializedValuesAndDeopt(JavaScriptFrame* frame) {
previously_materialized_objects);
CHECK_EQ(frames_[0].kind(), TranslatedFrame::kUnoptimizedFunction);
CHECK_EQ(frame->function(), frames_[0].front().GetRawValue());
Deoptimizer::DeoptimizeFunction(frame->function(), frame->LookupCode());
Deoptimizer::DeoptimizeFunction(frame->function(),
frame->LookupCodeT().ToCodeT());
}
}
......
......@@ -842,13 +842,11 @@ bool Code::contains(Isolate* isolate, Address inner_pointer) {
#ifdef V8_EXTERNAL_CODE_SPACE
bool CodeDataContainer::contains(Isolate* isolate, Address inner_pointer) {
if (is_off_heap_trampoline() &&
OffHeapBuiltinContains(isolate, inner_pointer)) {
return true;
if (is_off_heap_trampoline()) {
if (OffHeapBuiltinContains(isolate, inner_pointer)) return true;
if (V8_REMOVE_BUILTINS_CODE_OBJECTS) return false;
}
Code code = this->code();
return (code.address() <= inner_pointer) &&
(inner_pointer < code.address() + code.CodeSize());
return code().contains(isolate, inner_pointer);
}
#endif // V8_EXTERNAL_CODE_SPACE
......@@ -1081,6 +1079,7 @@ inline void Code::set_is_promise_rejection(bool value) {
}
inline bool Code::is_off_heap_trampoline() const {
if (V8_REMOVE_BUILTINS_CODE_OBJECTS) return false;
const uint32_t flags = RELAXED_READ_UINT32_FIELD(*this, kFlagsOffset);
return IsOffHeapTrampoline::decode(flags);
}
......
......@@ -912,11 +912,9 @@ bool DependentCode::MarkCodeForDeoptimization(
DisallowGarbageCollection no_gc;
bool marked_something = false;
IterateAndCompact([&](CodeT codet, DependencyGroups groups) {
IterateAndCompact([&](CodeT code, DependencyGroups groups) {
if ((groups & deopt_groups) == 0) return false;
// TODO(v8:11880): avoid roundtrips between cdc and code.
Code code = FromCodeT(codet);
if (!code.marked_for_deoptimization()) {
code.SetMarkedForDeoptimization("code dependencies");
marked_something = true;
......@@ -963,6 +961,13 @@ void Code::SetMarkedForDeoptimization(const char* reason) {
Deoptimizer::TraceMarkForDeoptimization(*this, reason);
}
#ifdef V8_EXTERNAL_CODE_SPACE
void CodeDataContainer::SetMarkedForDeoptimization(const char* reason) {
set_marked_for_deoptimization(true);
Deoptimizer::TraceMarkForDeoptimization(FromCodeT(*this), reason);
}
#endif
const char* DependentCode::DependencyGroupName(DependencyGroup group) {
switch (group) {
case kTransitionGroup:
......
......@@ -225,6 +225,8 @@ class CodeDataContainer : public HeapObject {
inline int GetOffsetFromInstructionStart(Isolate* isolate, Address pc) const;
void SetMarkedForDeoptimization(const char* reason);
#ifdef ENABLE_DISASSEMBLER
V8_EXPORT_PRIVATE void Disassemble(const char* name, std::ostream& os,
Isolate* isolate,
......
......@@ -269,7 +269,7 @@ void DeoptAllOsrLoopsContainingDeoptExit(Isolate* isolate, JSFunction function,
if (it.done()) return;
for (size_t i = 0, size = osr_codes.size(); i < size; i++) {
// Deoptimize type b osr'd loops
Deoptimizer::DeoptimizeFunction(function, FromCodeT(osr_codes[i]));
Deoptimizer::DeoptimizeFunction(function, osr_codes[i]);
}
// Visit after the first loop-with-deopt is found
int last_deopt_in_range_loop_jump_target;
......@@ -287,7 +287,7 @@ void DeoptAllOsrLoopsContainingDeoptExit(Isolate* isolate, JSFunction function,
last_deopt_in_range_loop_jump_target = it.GetJumpTargetOffset();
if (TryGetOptimizedOsrCode(isolate, vector, it, &code)) {
// Deoptimize type c osr'd loops
Deoptimizer::DeoptimizeFunction(function, FromCodeT(code));
Deoptimizer::DeoptimizeFunction(function, code);
}
// We've reached nesting level 0, i.e. the current JumpLoop concludes a
// top-level loop.
......@@ -302,7 +302,7 @@ void DeoptAllOsrLoopsContainingDeoptExit(Isolate* isolate, JSFunction function,
if (it.current_bytecode() != interpreter::Bytecode::kJumpLoop) continue;
if (TryGetOptimizedOsrCode(isolate, vector, it, &code)) {
// Deoptimize type a osr'd loops
Deoptimizer::DeoptimizeFunction(function, FromCodeT(code));
Deoptimizer::DeoptimizeFunction(function, code);
}
}
}
......@@ -360,11 +360,11 @@ RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) {
// the loop should pay for the deoptimization costs.
const BytecodeOffset osr_offset = optimized_code->osr_offset();
if (osr_offset.IsNone()) {
Deoptimizer::DeoptimizeFunction(*function, *optimized_code);
Deoptimizer::DeoptimizeFunction(*function, ToCodeT(*optimized_code));
DeoptAllOsrLoopsContainingDeoptExit(isolate, *function, deopt_exit_offset);
} else if (DeoptExitIsInsideOsrLoop(isolate, *function, deopt_exit_offset,
osr_offset)) {
Deoptimizer::DeoptimizeFunction(*function, *optimized_code);
Deoptimizer::DeoptimizeFunction(*function, ToCodeT(*optimized_code));
}
return ReadOnlyRoots(isolate).undefined_value();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment