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( ...@@ -855,11 +855,20 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromLoadHandler(
LoadHandler::DoAccessCheckOnLookupStartObjectBits::decode(smi_handler); LoadHandler::DoAccessCheckOnLookupStartObjectBits::decode(smi_handler);
bool lookup_on_lookup_start_object = bool lookup_on_lookup_start_object =
LoadHandler::LookupOnLookupStartObjectBits::decode(smi_handler); LoadHandler::LookupOnLookupStartObjectBits::decode(smi_handler);
if (do_access_check_on_lookup_start_object) return false;
if (lookup_on_lookup_start_object) return false; if (lookup_on_lookup_start_object) return false;
if (kind != LoadHandler::Kind::kConstantFromPrototype) return false; if (kind != LoadHandler::Kind::kConstantFromPrototype) return false;
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); BuildMapCheck(object, map);
}
Object validity_cell = handler.validity_cell(local_isolate_); Object validity_cell = handler.validity_cell(local_isolate_);
if (validity_cell.IsCell(local_isolate_)) { if (validity_cell.IsCell(local_isolate_)) {
......
...@@ -97,6 +97,7 @@ class MaglevGraphVerifier { ...@@ -97,6 +97,7 @@ class MaglevGraphVerifier {
case Opcode::kCheckMaps: case Opcode::kCheckMaps:
case Opcode::kCheckMapsWithMigration: case Opcode::kCheckMapsWithMigration:
case Opcode::kCheckSmi: case Opcode::kCheckSmi:
case Opcode::kCheckString:
case Opcode::kCheckedInternalizedString: case Opcode::kCheckedInternalizedString:
// TODO(victorgomes): Can we check that the input is Boolean? // TODO(victorgomes): Can we check that the input is Boolean?
case Opcode::kBranchIfToBooleanTrue: case Opcode::kBranchIfToBooleanTrue:
......
...@@ -748,6 +748,7 @@ void CheckMaps::GenerateCode(MaglevCodeGenState* code_gen_state, ...@@ -748,6 +748,7 @@ void CheckMaps::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) { const ProcessingState& state) {
Register object = ToRegister(receiver_input()); Register object = ToRegister(receiver_input());
__ AssertNotSmi(object);
__ Cmp(FieldOperand(object, HeapObject::kMapOffset), map().object()); __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map().object());
EmitEagerDeoptIf(not_equal, code_gen_state, DeoptimizeReason::kWrongMap, EmitEagerDeoptIf(not_equal, code_gen_state, DeoptimizeReason::kWrongMap,
this); this);
...@@ -781,6 +782,21 @@ void CheckHeapObject::GenerateCode(MaglevCodeGenState* code_gen_state, ...@@ -781,6 +782,21 @@ void CheckHeapObject::GenerateCode(MaglevCodeGenState* code_gen_state,
void CheckHeapObject::PrintParams(std::ostream& os, void CheckHeapObject::PrintParams(std::ostream& os,
MaglevGraphLabeller* graph_labeller) const {} 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( void CheckMapsWithMigration::AllocateVreg(
MaglevVregAllocationState* vreg_state) { MaglevVregAllocationState* vreg_state) {
UseRegister(receiver_input()); UseRegister(receiver_input());
...@@ -789,6 +805,7 @@ void CheckMapsWithMigration::GenerateCode(MaglevCodeGenState* code_gen_state, ...@@ -789,6 +805,7 @@ void CheckMapsWithMigration::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) { const ProcessingState& state) {
Register object = ToRegister(receiver_input()); Register object = ToRegister(receiver_input());
__ AssertNotSmi(object);
__ Cmp(FieldOperand(object, HeapObject::kMapOffset), map().object()); __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map().object());
JumpToDeferredIf( JumpToDeferredIf(
......
...@@ -162,6 +162,7 @@ class CompactInterpreterFrameState; ...@@ -162,6 +162,7 @@ class CompactInterpreterFrameState;
V(CheckMaps) \ V(CheckMaps) \
V(CheckSmi) \ V(CheckSmi) \
V(CheckHeapObject) \ V(CheckHeapObject) \
V(CheckString) \
V(CheckMapsWithMigration) \ V(CheckMapsWithMigration) \
V(StoreTaggedFieldNoWriteBarrier) \ V(StoreTaggedFieldNoWriteBarrier) \
V(StoreTaggedFieldWithWriteBarrier) \ V(StoreTaggedFieldWithWriteBarrier) \
...@@ -1997,6 +1998,22 @@ class CheckHeapObject : public FixedInputNodeT<1, CheckHeapObject> { ...@@ -1997,6 +1998,22 @@ class CheckHeapObject : public FixedInputNodeT<1, CheckHeapObject> {
void PrintParams(std::ostream&, MaglevGraphLabeller*) const; 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 class CheckMapsWithMigration
: public FixedInputNodeT<1, CheckMapsWithMigration> { : public FixedInputNodeT<1, CheckMapsWithMigration> {
using Base = 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