Commit 7350e7b2 authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

Get BytecodeArray via current frame where possible.

With BytecodeArray flushing the SFI->BytecodeArray pointer will become pseudo weak.
Instead of getting the bytecode array from the SFI, get it from the frame instead
(which is a strong pointer). Note: This won't actually change behaviour since the
fact that the bytecode array was on the frame will retain it strongly, however it
makes the contract that the BytecodeArray must exist at these points more explicit.

Updates code in runtime-profiler.cc, frames.cc and runtime-test.cc to do this.

BUG=v8:8395

Cq-Include-Trybots: luci.chromium.try:linux_chromium_headless_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: Id7a3e6857abd0e89bf238e9b0b01de4461df54e1
Reviewed-on: https://chromium-review.googlesource.com/c/1310193
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarMythri Alle <mythria@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57198}
parent 6b226ea2
...@@ -1655,7 +1655,7 @@ int InterpretedFrame::position() const { ...@@ -1655,7 +1655,7 @@ int InterpretedFrame::position() const {
int InterpretedFrame::LookupExceptionHandlerInTable( int InterpretedFrame::LookupExceptionHandlerInTable(
int* context_register, HandlerTable::CatchPrediction* prediction) { int* context_register, HandlerTable::CatchPrediction* prediction) {
HandlerTable table(function()->shared()->GetBytecodeArray()); HandlerTable table(GetBytecodeArray());
return table.LookupRange(GetBytecodeOffset(), context_register, prediction); return table.LookupRange(GetBytecodeOffset(), context_register, prediction);
} }
...@@ -1723,8 +1723,7 @@ void InterpretedFrame::WriteInterpreterRegister(int register_index, ...@@ -1723,8 +1723,7 @@ void InterpretedFrame::WriteInterpreterRegister(int register_index,
void InterpretedFrame::Summarize(std::vector<FrameSummary>* functions) const { void InterpretedFrame::Summarize(std::vector<FrameSummary>* functions) const {
DCHECK(functions->empty()); DCHECK(functions->empty());
AbstractCode* abstract_code = AbstractCode* abstract_code = AbstractCode::cast(GetBytecodeArray());
AbstractCode::cast(function()->shared()->GetBytecodeArray());
FrameSummary::JavaScriptFrameSummary summary( FrameSummary::JavaScriptFrameSummary summary(
isolate(), receiver(), function(), abstract_code, GetBytecodeOffset(), isolate(), receiver(), function(), abstract_code, GetBytecodeOffset(),
IsConstructor()); IsConstructor());
......
...@@ -112,7 +112,7 @@ void RuntimeProfiler::Optimize(JSFunction* function, ...@@ -112,7 +112,7 @@ void RuntimeProfiler::Optimize(JSFunction* function,
function->MarkForOptimization(ConcurrencyMode::kConcurrent); function->MarkForOptimization(ConcurrencyMode::kConcurrent);
} }
void RuntimeProfiler::AttemptOnStackReplacement(JavaScriptFrame* frame, void RuntimeProfiler::AttemptOnStackReplacement(InterpretedFrame* frame,
int loop_nesting_levels) { int loop_nesting_levels) {
JSFunction* function = frame->function(); JSFunction* function = frame->function();
SharedFunctionInfo* shared = function->shared(); SharedFunctionInfo* shared = function->shared();
...@@ -133,14 +133,13 @@ void RuntimeProfiler::AttemptOnStackReplacement(JavaScriptFrame* frame, ...@@ -133,14 +133,13 @@ void RuntimeProfiler::AttemptOnStackReplacement(JavaScriptFrame* frame,
} }
DCHECK_EQ(StackFrame::INTERPRETED, frame->type()); DCHECK_EQ(StackFrame::INTERPRETED, frame->type());
DCHECK(shared->HasBytecodeArray()); int level = frame->GetBytecodeArray()->osr_loop_nesting_level();
int level = shared->GetBytecodeArray()->osr_loop_nesting_level(); frame->GetBytecodeArray()->set_osr_loop_nesting_level(
shared->GetBytecodeArray()->set_osr_loop_nesting_level(
Min(level + loop_nesting_levels, AbstractCode::kMaxLoopNestingMarker)); Min(level + loop_nesting_levels, AbstractCode::kMaxLoopNestingMarker));
} }
void RuntimeProfiler::MaybeOptimize(JSFunction* function, void RuntimeProfiler::MaybeOptimize(JSFunction* function,
JavaScriptFrame* frame) { InterpretedFrame* frame) {
if (function->IsInOptimizationQueue()) { if (function->IsInOptimizationQueue()) {
if (FLAG_trace_opt_verbose) { if (FLAG_trace_opt_verbose) {
PrintF("[function "); PrintF("[function ");
...@@ -159,32 +158,28 @@ void RuntimeProfiler::MaybeOptimize(JSFunction* function, ...@@ -159,32 +158,28 @@ void RuntimeProfiler::MaybeOptimize(JSFunction* function,
if (function->shared()->optimization_disabled()) return; if (function->shared()->optimization_disabled()) return;
if (frame->is_optimized()) return; OptimizationReason reason =
ShouldOptimize(function, function->shared()->GetBytecodeArray());
OptimizationReason reason = ShouldOptimize(function, frame);
if (reason != OptimizationReason::kDoNotOptimize) { if (reason != OptimizationReason::kDoNotOptimize) {
Optimize(function, reason); Optimize(function, reason);
} }
} }
bool RuntimeProfiler::MaybeOSR(JSFunction* function, JavaScriptFrame* frame) { bool RuntimeProfiler::MaybeOSR(JSFunction* function, InterpretedFrame* frame) {
SharedFunctionInfo* shared = function->shared();
int ticks = function->feedback_vector()->profiler_ticks(); int ticks = function->feedback_vector()->profiler_ticks();
// TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller // TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller
// than kMaxToplevelSourceSize. // than kMaxToplevelSourceSize.
if (!frame->is_optimized() && if (function->IsMarkedForOptimization() ||
(function->IsMarkedForOptimization() ||
function->IsMarkedForConcurrentOptimization() || function->IsMarkedForConcurrentOptimization() ||
function->HasOptimizedCode())) { function->HasOptimizedCode()) {
// Attempt OSR if we are still running interpreted code even though the // Attempt OSR if we are still running interpreted code even though the
// the function has long been marked or even already been optimized. // the function has long been marked or even already been optimized.
int64_t allowance = int64_t allowance =
kOSRBytecodeSizeAllowanceBase + kOSRBytecodeSizeAllowanceBase +
static_cast<int64_t>(ticks) * kOSRBytecodeSizeAllowancePerTick; static_cast<int64_t>(ticks) * kOSRBytecodeSizeAllowancePerTick;
if (shared->GetBytecodeArray()->length() <= allowance) { if (function->shared()->GetBytecodeArray()->length() <= allowance) {
AttemptOnStackReplacement(frame); AttemptOnStackReplacement(frame);
} }
return true; return true;
...@@ -193,21 +188,19 @@ bool RuntimeProfiler::MaybeOSR(JSFunction* function, JavaScriptFrame* frame) { ...@@ -193,21 +188,19 @@ bool RuntimeProfiler::MaybeOSR(JSFunction* function, JavaScriptFrame* frame) {
} }
OptimizationReason RuntimeProfiler::ShouldOptimize(JSFunction* function, OptimizationReason RuntimeProfiler::ShouldOptimize(JSFunction* function,
JavaScriptFrame* frame) { BytecodeArray* bytecode) {
SharedFunctionInfo* shared = function->shared();
int ticks = function->feedback_vector()->profiler_ticks(); int ticks = function->feedback_vector()->profiler_ticks();
if (bytecode->length() > kMaxBytecodeSizeForOpt) {
if (shared->GetBytecodeArray()->length() > kMaxBytecodeSizeForOpt) {
return OptimizationReason::kDoNotOptimize; return OptimizationReason::kDoNotOptimize;
} }
int ticks_for_optimization = int ticks_for_optimization =
kProfilerTicksBeforeOptimization + kProfilerTicksBeforeOptimization +
(shared->GetBytecodeArray()->length() / kBytecodeSizeAllowancePerTick); (bytecode->length() / kBytecodeSizeAllowancePerTick);
if (ticks >= ticks_for_optimization) { if (ticks >= ticks_for_optimization) {
return OptimizationReason::kHotAndStable; return OptimizationReason::kHotAndStable;
} else if (!any_ic_changed_ && shared->GetBytecodeArray()->length() < } else if (!any_ic_changed_ &&
kMaxBytecodeSizeForEarlyOpt) { bytecode->length() < kMaxBytecodeSizeForEarlyOpt) {
// If no IC was patched since the last tick and this function is very // If no IC was patched since the last tick and this function is very
// small, optimistically optimize it now. // small, optimistically optimize it now.
return OptimizationReason::kSmallFunction; return OptimizationReason::kSmallFunction;
...@@ -220,7 +213,7 @@ OptimizationReason RuntimeProfiler::ShouldOptimize(JSFunction* function, ...@@ -220,7 +213,7 @@ OptimizationReason RuntimeProfiler::ShouldOptimize(JSFunction* function,
PrintF("ICs changed]\n"); PrintF("ICs changed]\n");
} else { } else {
PrintF(" too large for small function optimization: %d/%d]\n", PrintF(" too large for small function optimization: %d/%d]\n",
shared->GetBytecodeArray()->length(), kMaxBytecodeSizeForEarlyOpt); bytecode->length(), kMaxBytecodeSizeForEarlyOpt);
} }
} }
return OptimizationReason::kDoNotOptimize; return OptimizationReason::kDoNotOptimize;
...@@ -242,13 +235,13 @@ void RuntimeProfiler::MarkCandidatesForOptimization() { ...@@ -242,13 +235,13 @@ void RuntimeProfiler::MarkCandidatesForOptimization() {
frame_count++ < frame_count_limit && !it.done(); frame_count++ < frame_count_limit && !it.done();
it.Advance()) { it.Advance()) {
JavaScriptFrame* frame = it.frame(); JavaScriptFrame* frame = it.frame();
if (frame->is_optimized()) continue; if (!frame->is_interpreted()) continue;
JSFunction* function = frame->function(); JSFunction* function = frame->function();
DCHECK(function->shared()->is_compiled()); DCHECK(function->shared()->is_compiled());
if (!function->shared()->IsInterpreted()) continue; if (!function->shared()->IsInterpreted()) continue;
MaybeOptimize(function, frame); MaybeOptimize(function, InterpretedFrame::cast(frame));
// TODO(leszeks): Move this increment to before the maybe optimize checks, // TODO(leszeks): Move this increment to before the maybe optimize checks,
// and update the tests to assume the increment has already happened. // and update the tests to assume the increment has already happened.
......
...@@ -10,8 +10,9 @@ ...@@ -10,8 +10,9 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class BytecodeArray;
class Isolate; class Isolate;
class JavaScriptFrame; class InterpretedFrame;
class JSFunction; class JSFunction;
enum class OptimizationReason : uint8_t; enum class OptimizationReason : uint8_t;
...@@ -23,16 +24,16 @@ class RuntimeProfiler { ...@@ -23,16 +24,16 @@ class RuntimeProfiler {
void NotifyICChanged() { any_ic_changed_ = true; } void NotifyICChanged() { any_ic_changed_ = true; }
void AttemptOnStackReplacement(JavaScriptFrame* frame, void AttemptOnStackReplacement(InterpretedFrame* frame,
int nesting_levels = 1); int nesting_levels = 1);
private: private:
void MaybeOptimize(JSFunction* function, JavaScriptFrame* frame); void MaybeOptimize(JSFunction* function, InterpretedFrame* frame);
// Potentially attempts OSR from and returns whether no other // Potentially attempts OSR from and returns whether no other
// optimization attempts should be made. // optimization attempts should be made.
bool MaybeOSR(JSFunction* function, JavaScriptFrame* frame); bool MaybeOSR(JSFunction* function, InterpretedFrame* frame);
OptimizationReason ShouldOptimize(JSFunction* function, OptimizationReason ShouldOptimize(JSFunction* function,
JavaScriptFrame* frame); BytecodeArray* bytecode_array);
void Optimize(JSFunction* function, OptimizationReason reason); void Optimize(JSFunction* function, OptimizationReason reason);
void Baseline(JSFunction* function, OptimizationReason reason); void Baseline(JSFunction* function, OptimizationReason reason);
......
...@@ -299,7 +299,8 @@ RUNTIME_FUNCTION(Runtime_OptimizeOsr) { ...@@ -299,7 +299,8 @@ RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
// Make the profiler arm all back edges in unoptimized code. // Make the profiler arm all back edges in unoptimized code.
if (it.frame()->type() == StackFrame::INTERPRETED) { if (it.frame()->type() == StackFrame::INTERPRETED) {
isolate->runtime_profiler()->AttemptOnStackReplacement( isolate->runtime_profiler()->AttemptOnStackReplacement(
it.frame(), AbstractCode::kMaxLoopNestingMarker); InterpretedFrame::cast(it.frame()),
AbstractCode::kMaxLoopNestingMarker);
} }
return ReadOnlyRoots(isolate).undefined_value(); return ReadOnlyRoots(isolate).undefined_value();
......
...@@ -26,7 +26,7 @@ return x + b; ...@@ -26,7 +26,7 @@ return x + b;
--- ---
Break location after LiveEdit: Break location after LiveEdit:
var x = a; var x = a;
var x = #3; #var x = 3;
debugger; debugger;
stackChanged: true stackChanged: true
...@@ -62,12 +62,12 @@ var x = 1; ...@@ -62,12 +62,12 @@ var x = 1;
--- ---
Break location after LiveEdit: Break location after LiveEdit:
function boo() { function boo() {
var x = #3; #var x = 3;
debugger; debugger;
stackChanged: true stackChanged: true
Protocol.Debugger.stepInto Protocol.Debugger.stepInto
var x = 3; function boo() {
#debugger; var x = #3;
var x = 1; debugger;
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