Commit a6f3fce3 authored by Georg Neis's avatar Georg Neis Committed by V8 LUCI CQ

Fix a DCHECK failure with broken asm.js functions

Fixed: chromium:1236286
Change-Id: I90106fce4d6e747f35c638ab00bf9a1696c8eb77
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3109668
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76462}
parent 79c1b995
...@@ -250,7 +250,7 @@ void RuntimeProfiler::MarkCandidatesForOptimization(JavaScriptFrame* frame) { ...@@ -250,7 +250,7 @@ void RuntimeProfiler::MarkCandidatesForOptimization(JavaScriptFrame* frame) {
MarkCandidatesForOptimizationScope scope(this); MarkCandidatesForOptimizationScope scope(this);
JSFunction function = frame->function(); JSFunction function = frame->function();
CodeKind code_kind = function.GetActiveTier(); CodeKind code_kind = function.GetActiveTier().value();
DCHECK(function.shared().is_compiled()); DCHECK(function.shared().is_compiled());
DCHECK(function.shared().IsInterpreted()); DCHECK(function.shared().IsInterpreted());
......
...@@ -55,7 +55,7 @@ void JSFunction::ClearOptimizationMarker() { ...@@ -55,7 +55,7 @@ void JSFunction::ClearOptimizationMarker() {
} }
bool JSFunction::ChecksOptimizationMarker() { bool JSFunction::ChecksOptimizationMarker() {
return code(kAcquireLoad).checks_optimization_marker(); return code().checks_optimization_marker();
} }
bool JSFunction::IsMarkedForOptimization() { bool JSFunction::IsMarkedForOptimization() {
......
...@@ -19,19 +19,10 @@ namespace v8 { ...@@ -19,19 +19,10 @@ namespace v8 {
namespace internal { namespace internal {
CodeKinds JSFunction::GetAttachedCodeKinds() const { CodeKinds JSFunction::GetAttachedCodeKinds() const {
// Note: There's a special case when bytecode has been aged away. After const CodeKind kind = code().kind();
// flushing the bytecode, the JSFunction will still have the interpreter
// entry trampoline attached, but the bytecode is no longer available.
Code code = this->code(kAcquireLoad);
if (code.is_interpreter_trampoline_builtin()) {
return CodeKindFlag::INTERPRETED_FUNCTION;
}
const CodeKind kind = code.kind();
if (!CodeKindIsJSFunction(kind)) return {}; if (!CodeKindIsJSFunction(kind)) return {};
if (CodeKindIsOptimizedJSFunction(kind) &&
if (CodeKindIsOptimizedJSFunction(kind) && code.marked_for_deoptimization()) { code().marked_for_deoptimization()) {
// Nothing is attached.
return {}; return {};
} }
return CodeKindToCodeKindFlag(kind); return CodeKindToCodeKindFlag(kind);
...@@ -90,7 +81,8 @@ namespace { ...@@ -90,7 +81,8 @@ namespace {
// Returns false if no highest tier exists (i.e. the function is not compiled), // Returns false if no highest tier exists (i.e. the function is not compiled),
// otherwise returns true and sets highest_tier. // otherwise returns true and sets highest_tier.
bool HighestTierOf(CodeKinds kinds, CodeKind* highest_tier) { V8_WARN_UNUSED_RESULT bool HighestTierOf(CodeKinds kinds,
CodeKind* highest_tier) {
DCHECK_EQ((kinds & ~kJSFunctionCodeKindsMask), 0); DCHECK_EQ((kinds & ~kJSFunctionCodeKindsMask), 0);
if ((kinds & CodeKindFlag::TURBOFAN) != 0) { if ((kinds & CodeKindFlag::TURBOFAN) != 0) {
*highest_tier = CodeKind::TURBOFAN; *highest_tier = CodeKind::TURBOFAN;
...@@ -111,33 +103,43 @@ bool HighestTierOf(CodeKinds kinds, CodeKind* highest_tier) { ...@@ -111,33 +103,43 @@ bool HighestTierOf(CodeKinds kinds, CodeKind* highest_tier) {
} // namespace } // namespace
bool JSFunction::ActiveTierIsIgnition() const { base::Optional<CodeKind> JSFunction::GetActiveTier() const {
if (!shared().HasBytecodeArray()) return false; #if V8_ENABLE_WEBASSEMBLY
bool result = (GetActiveTier() == CodeKind::INTERPRETED_FUNCTION); // Asm/Wasm functions are currently not supported. For simplicity, this
// includes invalid asm.js functions whose code hasn't yet been updated to
// CompileLazy but is still the InstantiateAsmJs builtin.
if (shared().HasAsmWasmData() ||
code().builtin_id() == Builtin::kInstantiateAsmJs) {
return {};
}
#endif // V8_ENABLE_WEBASSEMBLY
CodeKind highest_tier;
if (!HighestTierOf(GetAvailableCodeKinds(), &highest_tier)) return {};
#ifdef DEBUG #ifdef DEBUG
Code code = this->code(kAcquireLoad); CHECK(highest_tier == CodeKind::TURBOFAN ||
DCHECK_IMPLIES(result, code.is_interpreter_trampoline_builtin() || highest_tier == CodeKind::BASELINE ||
(CodeKindIsOptimizedJSFunction(code.kind()) && highest_tier == CodeKind::TURBOPROP ||
code.marked_for_deoptimization()) || highest_tier == CodeKind::INTERPRETED_FUNCTION);
(code.builtin_id() == Builtin::kCompileLazy &&
shared().IsInterpreted())); if (highest_tier == CodeKind::INTERPRETED_FUNCTION) {
CHECK(code().is_interpreter_trampoline_builtin() ||
(CodeKindIsOptimizedJSFunction(code().kind()) &&
code().marked_for_deoptimization()) ||
(code().builtin_id() == Builtin::kCompileLazy &&
shared().IsInterpreted()));
}
#endif // DEBUG #endif // DEBUG
return result;
}
CodeKind JSFunction::GetActiveTier() const {
CodeKind highest_tier;
DCHECK(shared().is_compiled());
HighestTierOf(GetAvailableCodeKinds(), &highest_tier);
DCHECK(highest_tier == CodeKind::TURBOFAN ||
highest_tier == CodeKind::BASELINE ||
highest_tier == CodeKind::TURBOPROP ||
highest_tier == CodeKind::INTERPRETED_FUNCTION);
return highest_tier; return highest_tier;
} }
bool JSFunction::ActiveTierIsIgnition() const {
return GetActiveTier() == CodeKind::INTERPRETED_FUNCTION;
}
bool JSFunction::ActiveTierIsTurbofan() const { bool JSFunction::ActiveTierIsTurbofan() const {
if (!shared().HasBytecodeArray()) return false;
return GetActiveTier() == CodeKind::TURBOFAN; return GetActiveTier() == CodeKind::TURBOFAN;
} }
...@@ -145,27 +147,20 @@ bool JSFunction::ActiveTierIsBaseline() const { ...@@ -145,27 +147,20 @@ bool JSFunction::ActiveTierIsBaseline() const {
return GetActiveTier() == CodeKind::BASELINE; return GetActiveTier() == CodeKind::BASELINE;
} }
bool JSFunction::ActiveTierIsIgnitionOrBaseline() const {
return ActiveTierIsIgnition() || ActiveTierIsBaseline();
}
bool JSFunction::ActiveTierIsToptierTurboprop() const { bool JSFunction::ActiveTierIsToptierTurboprop() const {
if (!FLAG_turboprop_as_toptier) return false; return FLAG_turboprop_as_toptier && GetActiveTier() == CodeKind::TURBOPROP;
if (!shared().HasBytecodeArray()) return false;
return GetActiveTier() == CodeKind::TURBOPROP && FLAG_turboprop_as_toptier;
} }
bool JSFunction::ActiveTierIsMidtierTurboprop() const { bool JSFunction::ActiveTierIsMidtierTurboprop() const {
if (!FLAG_turboprop) return false; return FLAG_turboprop && !FLAG_turboprop_as_toptier &&
if (!shared().HasBytecodeArray()) return false; GetActiveTier() == CodeKind::TURBOPROP;
return GetActiveTier() == CodeKind::TURBOPROP && !FLAG_turboprop_as_toptier;
} }
CodeKind JSFunction::NextTier() const { CodeKind JSFunction::NextTier() const {
if (V8_UNLIKELY(FLAG_turboprop) && ActiveTierIsMidtierTurboprop()) { if (V8_UNLIKELY(FLAG_turboprop) && ActiveTierIsMidtierTurboprop()) {
return CodeKind::TURBOFAN; return CodeKind::TURBOFAN;
} else if (V8_UNLIKELY(FLAG_turboprop)) { } else if (V8_UNLIKELY(FLAG_turboprop)) {
DCHECK(ActiveTierIsIgnitionOrBaseline()); DCHECK(ActiveTierIsIgnition() || ActiveTierIsBaseline());
return CodeKind::TURBOPROP; return CodeKind::TURBOPROP;
} }
return CodeKind::TURBOFAN; return CodeKind::TURBOFAN;
......
...@@ -106,7 +106,8 @@ class JSFunction : public JSFunctionOrBoundFunction { ...@@ -106,7 +106,8 @@ class JSFunction : public JSFunctionOrBoundFunction {
// indirect means such as the feedback vector's optimized code cache. // indirect means such as the feedback vector's optimized code cache.
// - Active: the single code kind that would be executed if this function // - Active: the single code kind that would be executed if this function
// were called in its current state. Note that there may not be an active // were called in its current state. Note that there may not be an active
// code kind if the function is not compiled. // code kind if the function is not compiled. Also, asm/wasm functions are
// currently not supported.
// //
// Note: code objects that are marked_for_deoptimization are not part of the // Note: code objects that are marked_for_deoptimization are not part of the
// attached/available/active sets. This is because the JSFunction might have // attached/available/active sets. This is because the JSFunction might have
...@@ -120,11 +121,10 @@ class JSFunction : public JSFunctionOrBoundFunction { ...@@ -120,11 +121,10 @@ class JSFunction : public JSFunctionOrBoundFunction {
bool HasAttachedCodeKind(CodeKind kind) const; bool HasAttachedCodeKind(CodeKind kind) const;
bool HasAvailableCodeKind(CodeKind kind) const; bool HasAvailableCodeKind(CodeKind kind) const;
CodeKind GetActiveTier() const; base::Optional<CodeKind> GetActiveTier() const;
V8_EXPORT_PRIVATE bool ActiveTierIsIgnition() const; V8_EXPORT_PRIVATE bool ActiveTierIsIgnition() const;
bool ActiveTierIsTurbofan() const; bool ActiveTierIsTurbofan() const;
bool ActiveTierIsBaseline() const; bool ActiveTierIsBaseline() const;
bool ActiveTierIsIgnitionOrBaseline() const;
bool ActiveTierIsMidtierTurboprop() const; bool ActiveTierIsMidtierTurboprop() const;
bool ActiveTierIsToptierTurboprop() const; bool ActiveTierIsToptierTurboprop() const;
......
...@@ -71,6 +71,18 @@ V8_WARN_UNUSED_RESULT Object ReturnFuzzSafe(Object value, Isolate* isolate) { ...@@ -71,6 +71,18 @@ V8_WARN_UNUSED_RESULT Object ReturnFuzzSafe(Object value, Isolate* isolate) {
if (!args[index].IsBoolean()) return CrashUnlessFuzzing(isolate); \ if (!args[index].IsBoolean()) return CrashUnlessFuzzing(isolate); \
bool name = args[index].IsTrue(isolate); bool name = args[index].IsTrue(isolate);
bool IsAsmWasmFunction(Isolate* isolate, JSFunction function) {
DisallowGarbageCollection no_gc;
#if V8_ENABLE_WEBASSEMBLY
// For simplicity we include invalid asm.js functions whose code hasn't yet
// been updated to CompileLazy but is still the InstantiateAsmJs builtin.
return function.shared().HasAsmWasmData() ||
function.code().builtin_id() == Builtin::kInstantiateAsmJs;
#else
return false;
#endif // V8_ENABLE_WEBASSEMBLY
}
} // namespace } // namespace
RUNTIME_FUNCTION(Runtime_ClearMegamorphicStubCache) { RUNTIME_FUNCTION(Runtime_ClearMegamorphicStubCache) {
...@@ -243,11 +255,9 @@ bool CanOptimizeFunction(Handle<JSFunction> function, Isolate* isolate, ...@@ -243,11 +255,9 @@ bool CanOptimizeFunction(Handle<JSFunction> function, Isolate* isolate,
return CrashUnlessFuzzingReturnFalse(isolate); return CrashUnlessFuzzingReturnFalse(isolate);
} }
#if V8_ENABLE_WEBASSEMBLY if (IsAsmWasmFunction(isolate, *function)) {
if (function->shared().HasAsmWasmData()) {
return CrashUnlessFuzzingReturnFalse(isolate); return CrashUnlessFuzzingReturnFalse(isolate);
} }
#endif // V8_ENABLE_WEBASSEMBLY
if (FLAG_testing_d8_test_runner) { if (FLAG_testing_d8_test_runner) {
PendingOptimizationTable::MarkedForOptimization(isolate, function); PendingOptimizationTable::MarkedForOptimization(isolate, function);
...@@ -425,9 +435,7 @@ RUNTIME_FUNCTION(Runtime_PrepareFunctionForOptimization) { ...@@ -425,9 +435,7 @@ RUNTIME_FUNCTION(Runtime_PrepareFunctionForOptimization) {
return CrashUnlessFuzzing(isolate); return CrashUnlessFuzzing(isolate);
} }
#if V8_ENABLE_WEBASSEMBLY if (IsAsmWasmFunction(isolate, *function)) return CrashUnlessFuzzing(isolate);
if (function->shared().HasAsmWasmData()) return CrashUnlessFuzzing(isolate);
#endif // V8_ENABLE_WEBASSEMBLY
// Hold onto the bytecode array between marking and optimization to ensure // Hold onto the bytecode array between marking and optimization to ensure
// it's not flushed. // it's not flushed.
......
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --fuzzing
// Without --fuzzing, %PrepareFunctionForOptimization would fail.
for (let i = 0; i < 2; i++) {
try { new this.invalid(); } catch {}
function invalid(x) {
"use asm";
var y = x.Math.fround;
function foo() {}
return {foo: foo};
}
%PrepareFunctionForOptimization(invalid);
%OptimizeFunctionOnNextCall(invalid);
}
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