From ed93bef7ab786d5367c2ae7882922c23aa0eda64 Mon Sep 17 00:00:00 2001 From: Toon Verwaest Date: Tue, 18 Jul 2023 15:48:29 +0200 Subject: [PATCH] [maglev] Fix default constructor instantiation The new.target may not be in the correct state for fast instantiation. Bug: v8:7700, chromium:1465326 Change-Id: I09f92576c0b5573e902ae3b2210a7b5fdbd1e415 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4694007 Commit-Queue: Toon Verwaest Reviewed-by: Leszek Swirski Cr-Commit-Position: refs/heads/main@{#89006} --- src/maglev/maglev-graph-builder.cc | 12 ++++++++- src/maglev/maglev-graph-builder.h | 3 +++ .../maglev/regress/regress-crbug-1465326.js | 25 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 test/mjsunit/maglev/regress/regress-crbug-1465326.js diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.cc index d5f612898bb8..2c5227edc504 100644 --- a/src/maglev/maglev-graph-builder.cc +++ b/src/maglev/maglev-graph-builder.cc @@ -5347,6 +5347,14 @@ void MaglevGraphBuilder::VisitGetSuperConstructor() { StoreRegister(iterator_.GetRegisterOperand(0), map_proto); } +bool MaglevGraphBuilder::HasValidInitialMap( + compiler::JSFunctionRef new_target, compiler::JSFunctionRef constructor) { + if (!new_target.map(broker()).has_prototype_slot()) return false; + if (!new_target.has_initial_map(broker())) return false; + compiler::MapRef initial_map = new_target.initial_map(broker()); + return initial_map.GetConstructor(broker()).equals(constructor); +} + void MaglevGraphBuilder::VisitFindNonDefaultConstructorOrConstruct() { ValueNode* this_function = LoadRegisterTagged(0); ValueNode* new_target = LoadRegisterTagged(1); @@ -5380,7 +5388,9 @@ void MaglevGraphBuilder::VisitFindNonDefaultConstructorOrConstruct() { TryGetConstant(new_target); if (kind == FunctionKind::kDefaultBaseConstructor) { ValueNode* object; - if (new_target_function && new_target_function->IsJSFunction()) { + if (new_target_function && new_target_function->IsJSFunction() && + HasValidInitialMap(new_target_function->AsJSFunction(), + current_function)) { object = BuildAllocateFastObject( FastObject(new_target_function->AsJSFunction(), zone(), broker()), diff --git a/src/maglev/maglev-graph-builder.h b/src/maglev/maglev-graph-builder.h index 0abb4a8a3a0c..d92354c4ee6f 100644 --- a/src/maglev/maglev-graph-builder.h +++ b/src/maglev/maglev-graph-builder.h @@ -1884,6 +1884,9 @@ class MaglevGraphBuilder { void MergeDeadLoopIntoFrameState(int target); void MergeIntoInlinedReturnFrameState(BasicBlock* block); + bool HasValidInitialMap(compiler::JSFunctionRef new_target, + compiler::JSFunctionRef constructor); + enum JumpType { kJumpIfTrue, kJumpIfFalse }; enum class BranchSpecializationMode { kDefault, kAlwaysBoolean }; JumpType NegateJumpType(JumpType jump_type); diff --git a/test/mjsunit/maglev/regress/regress-crbug-1465326.js b/test/mjsunit/maglev/regress/regress-crbug-1465326.js new file mode 100644 index 000000000000..6e01c1ec0262 --- /dev/null +++ b/test/mjsunit/maglev/regress/regress-crbug-1465326.js @@ -0,0 +1,25 @@ +// Copyright 2023 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: --maglev --allow-natives-syntax + +class A {} + +var x = Function; + +class B extends A { + constructor() { + x = new.target; + super(); + } +} +function construct() { + return Reflect.construct(B, [], Function); +} +%PrepareFunctionForOptimization(B); +construct(); +construct(); +%OptimizeMaglevOnNextCall(B); +var arr = construct(); +console.log(arr.prototype);