Commit c74f34b1 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Add CheckString for prototype constant loads

For prototype loads from strings, we require an access check, since
string maps are shared between native contexts. This makes our prototype
constant load optimisation bail out to a generic load.

We can, however skip this check given the knowledge that this is a
prototype load from a primitive, and instead emit a string check. We can
also be a slight bit more tolerant of multiple different string maps,
same as TF.

Bug: v8:7700
Change-Id: I4ad858cadea68246f903443d19fa6cdd65a14564
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3762576Reviewed-by: 's avatarVictor Gomes <victorgomes@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81751}
parent f74d6931
......@@ -855,11 +855,20 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromLoadHandler(
LoadHandler::DoAccessCheckOnLookupStartObjectBits::decode(smi_handler);
bool lookup_on_lookup_start_object =
LoadHandler::LookupOnLookupStartObjectBits::decode(smi_handler);
if (do_access_check_on_lookup_start_object) return false;
if (lookup_on_lookup_start_object) return false;
if (kind != LoadHandler::Kind::kConstantFromPrototype) return false;
BuildMapCheck(object, map);
if (map.IsStringMap()) {
// Check for string maps before checking if we need to do an access check.
// Primitive strings always get the prototype from the native context
// they're operated on, so they don't need the access check.
AddNewNode<CheckHeapObject>({object});
AddNewNode<CheckString>({object});
} else if (do_access_check_on_lookup_start_object) {
return false;
} else {
BuildMapCheck(object, map);
}
Object validity_cell = handler.validity_cell(local_isolate_);
if (validity_cell.IsCell(local_isolate_)) {
......
......@@ -97,6 +97,7 @@ class MaglevGraphVerifier {
case Opcode::kCheckMaps:
case Opcode::kCheckMapsWithMigration:
case Opcode::kCheckSmi:
case Opcode::kCheckString:
case Opcode::kCheckedInternalizedString:
// TODO(victorgomes): Can we check that the input is Boolean?
case Opcode::kBranchIfToBooleanTrue:
......
......@@ -748,6 +748,7 @@ void CheckMaps::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
Register object = ToRegister(receiver_input());
__ AssertNotSmi(object);
__ Cmp(FieldOperand(object, HeapObject::kMapOffset), map().object());
EmitEagerDeoptIf(not_equal, code_gen_state, DeoptimizeReason::kWrongMap,
this);
......@@ -781,6 +782,21 @@ void CheckHeapObject::GenerateCode(MaglevCodeGenState* code_gen_state,
void CheckHeapObject::PrintParams(std::ostream& os,
MaglevGraphLabeller* graph_labeller) const {}
void CheckString::AllocateVreg(MaglevVregAllocationState* vreg_state) {
UseRegister(receiver_input());
}
void CheckString::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
Register object = ToRegister(receiver_input());
__ AssertNotSmi(object);
__ LoadMap(kScratchRegister, object);
__ CmpInstanceTypeRange(kScratchRegister, kScratchRegister, FIRST_STRING_TYPE,
LAST_STRING_TYPE);
EmitEagerDeoptIf(above, code_gen_state, DeoptimizeReason::kNotAString, this);
}
void CheckString::PrintParams(std::ostream& os,
MaglevGraphLabeller* graph_labeller) const {}
void CheckMapsWithMigration::AllocateVreg(
MaglevVregAllocationState* vreg_state) {
UseRegister(receiver_input());
......@@ -789,6 +805,7 @@ void CheckMapsWithMigration::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
Register object = ToRegister(receiver_input());
__ AssertNotSmi(object);
__ Cmp(FieldOperand(object, HeapObject::kMapOffset), map().object());
JumpToDeferredIf(
......
......@@ -162,6 +162,7 @@ class CompactInterpreterFrameState;
V(CheckMaps) \
V(CheckSmi) \
V(CheckHeapObject) \
V(CheckString) \
V(CheckMapsWithMigration) \
V(StoreTaggedFieldNoWriteBarrier) \
V(StoreTaggedFieldWithWriteBarrier) \
......@@ -1997,6 +1998,22 @@ class CheckHeapObject : public FixedInputNodeT<1, CheckHeapObject> {
void PrintParams(std::ostream&, MaglevGraphLabeller*) const;
};
class CheckString : public FixedInputNodeT<1, CheckString> {
using Base = FixedInputNodeT<1, CheckString>;
public:
explicit CheckString(uint64_t bitfield) : Base(bitfield) {}
static constexpr OpProperties kProperties = OpProperties::EagerDeopt();
static constexpr int kReceiverIndex = 0;
Input& receiver_input() { return input(kReceiverIndex); }
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const;
};
class CheckMapsWithMigration
: public FixedInputNodeT<1, CheckMapsWithMigration> {
using Base = FixedInputNodeT<1, CheckMapsWithMigration>;
......
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