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