Commit fd4cc2b2 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[ptr-compr][csa] Preparing for smi-corrupting decompression

This CL fixes comparison operations that take into account full-word
value instead of the lower 32 bits and tweaks some CSA helper functions
for smi-corrupting decompression.

Bug: v8:9706
Change-Id: I50e38a9f34b911ec0b8dd4e21298417bf23160aa
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1824943Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63995}
parent dcf3b663
......@@ -112,6 +112,8 @@ using PlatformSmiTagging = SmiTagging<kApiInt32Size>;
using PlatformSmiTagging = SmiTagging<kApiTaggedSize>;
#endif
// TODO(ishell): Consinder adding kSmiShiftBits = kSmiShiftSize + kSmiTagSize
// since it's used much more often than the inividual constants.
const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize;
const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize;
const int kSmiMinValue = static_cast<int>(PlatformSmiTagging::kSmiMinValue);
......
......@@ -2615,6 +2615,7 @@ extern macro BitcastWordToTaggedSigned(uintptr): Smi;
extern macro BitcastWordToTagged(intptr): Object;
extern macro BitcastWordToTagged(uintptr): Object;
extern macro BitcastTaggedToWord(Tagged): intptr;
extern macro BitcastTaggedToWordForTagAndSmiBits(Tagged): intptr;
intrinsic %FromConstexpr<To: type, From: type>(b: From): To;
macro FromConstexpr<To: type, From: type>(o: From): To;
......
......@@ -1101,7 +1101,7 @@ TF_BUILTIN(CreateObjectWithoutProperties, ObjectBuiltinsAssembler) {
LoadMapPrototypeInfo(LoadMap(CAST(prototype)), &call_runtime);
TNode<MaybeObject> maybe_map = LoadMaybeWeakObjectField(
prototype_info, PrototypeInfo::kObjectCreateMapOffset);
GotoIf(IsStrongReferenceTo(maybe_map, UndefinedConstant()), &call_runtime);
GotoIf(TaggedEqual(maybe_map, UndefinedConstant()), &call_runtime);
map = CAST(GetHeapObjectAssumeWeak(maybe_map, &call_runtime));
Goto(&instantiate_map);
}
......@@ -1197,8 +1197,7 @@ TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) {
Comment("Load ObjectCreateMap from PrototypeInfo");
TNode<MaybeObject> maybe_map = LoadMaybeWeakObjectField(
prototype_info, PrototypeInfo::kObjectCreateMapOffset);
GotoIf(IsStrongReferenceTo(maybe_map, UndefinedConstant()),
&call_runtime);
GotoIf(TaggedEqual(maybe_map, UndefinedConstant()), &call_runtime);
map = CAST(GetHeapObjectAssumeWeak(maybe_map, &call_runtime));
Goto(&instantiate_map);
}
......
......@@ -77,7 +77,7 @@ class BuiltinArguments : public Arguments {
RuntimeCallCounterId::kBuiltin_##name); \
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \
"V8.Builtin_" #name); \
return Builtin_Impl_##name(args, isolate).ptr(); \
return CONVERT_OBJECT(Builtin_Impl_##name(args, isolate)); \
} \
\
V8_WARN_UNUSED_RESULT Address Builtin_##name( \
......@@ -87,7 +87,7 @@ class BuiltinArguments : public Arguments {
return Builtin_Impl_Stats_##name(args_length, args_object, isolate); \
} \
BuiltinArguments args(args_length, args_object); \
return Builtin_Impl_##name(args, isolate).ptr(); \
return CONVERT_OBJECT(Builtin_Impl_##name(args, isolate)); \
} \
\
V8_WARN_UNUSED_RESULT static Object Builtin_Impl_##name( \
......
......@@ -24,8 +24,8 @@ Cast<FrameType>(o: Object): FrameType
labels CastError {
if (TaggedIsNotSmi(o)) goto CastError;
assert(
(Convert<uintptr>(BitcastTaggedToWord(o)) >>> kSmiTagSize) <
kFrameTypeCount);
Convert<int32>(BitcastTaggedToWordForTagAndSmiBits(o)) <
Convert<int32>(kFrameTypeCount << kSmiTagSize));
return %RawDownCast<FrameType>(o);
}
......
......@@ -23,7 +23,7 @@ namespace typed_array_slice {
// of src and result array are the same and they are not sharing the
// same buffer, use memmove.
if (srcKind != destInfo.kind) goto IfSlow;
if (BitcastTaggedToWord(dest.buffer) == BitcastTaggedToWord(src.buffer)) {
if (dest.buffer == src.buffer) {
goto IfSlow;
}
......
This diff is collapsed.
......@@ -366,6 +366,16 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
#error Unknown architecture.
#endif
// Pointer compression specific. Returns true if the upper 32 bits of a Smi
// contain the sign of a lower 32 bits (i.e. not corrupted) so that the Smi
// can be directly used as an index in element offset computation.
TNode<BoolT> IsValidSmiIndex(TNode<Smi> smi);
// Pointer compression specific. Ensures that the upper 32 bits of a Smi
// contain the sign of a lower 32 bits so that the Smi can be directly used
// as an index in element offset computation.
TNode<Smi> NormalizeSmiIndex(TNode<Smi> smi_index);
TNode<Smi> TaggedToSmi(TNode<Object> value, Label* fail) {
GotoIf(TaggedIsNotSmi(value), fail);
return UncheckedCast<Smi>(value);
......@@ -1223,7 +1233,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<BoolT> IsWeakOrCleared(TNode<MaybeObject> value);
TNode<BoolT> IsCleared(TNode<MaybeObject> value);
TNode<BoolT> IsNotCleared(TNode<MaybeObject> value);
TNode<BoolT> IsNotCleared(TNode<MaybeObject> value) {
return Word32BinaryNot(IsCleared(value));
}
// Removes the weak bit + asserts it was set.
TNode<HeapObject> GetHeapObjectAssumeWeak(TNode<MaybeObject> value);
......@@ -1231,12 +1243,15 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<HeapObject> GetHeapObjectAssumeWeak(TNode<MaybeObject> value,
Label* if_cleared);
TNode<BoolT> IsWeakReferenceTo(TNode<MaybeObject> object,
TNode<Object> value);
TNode<BoolT> IsNotWeakReferenceTo(TNode<MaybeObject> object,
TNode<Object> value);
TNode<BoolT> IsStrongReferenceTo(TNode<MaybeObject> object,
TNode<Object> value);
// Checks if |maybe_object| is a weak reference to given |heap_object|.
// Works for both any tagged |maybe_object| values.
TNode<BoolT> IsWeakReferenceTo(TNode<MaybeObject> maybe_object,
TNode<HeapObject> heap_object);
// Returns true if the |object| is a HeapObject and |maybe_object| is a weak
// reference to |object|.
// The |maybe_object| must not be a Smi.
TNode<BoolT> IsWeakReferenceToObject(TNode<MaybeObject> maybe_object,
TNode<Object> object);
TNode<MaybeObject> MakeWeak(TNode<HeapObject> value);
......@@ -1939,16 +1954,17 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
enum class DestroySource { kNo, kYes };
// Collect the callable |target| feedback for either a CALL_IC or
// Collect the callable |maybe_target| feedback for either a CALL_IC or
// an INSTANCEOF_IC in the |feedback_vector| at |slot_id|.
void CollectCallableFeedback(TNode<Object> target, TNode<Context> context,
void CollectCallableFeedback(TNode<Object> maybe_target,
TNode<Context> context,
TNode<FeedbackVector> feedback_vector,
TNode<UintPtrT> slot_id);
// Collect CALL_IC feedback for |target| function in the
// Collect CALL_IC feedback for |maybe_target| function in the
// |feedback_vector| at |slot_id|, and the call counts in
// the |feedback_vector| at |slot_id+1|.
void CollectCallFeedback(TNode<Object> target, TNode<Context> context,
void CollectCallFeedback(TNode<Object> maybe_target, TNode<Context> context,
TNode<HeapObject> maybe_feedback_vector,
TNode<UintPtrT> slot_id);
......@@ -3697,7 +3713,13 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<AllocationSite> allocation_site, TNode<IntPtrT> size_in_bytes);
TNode<BoolT> IsValidSmi(TNode<Smi> smi);
Node* SmiShiftBitsConstant();
TNode<IntPtrT> SmiShiftBitsConstant() {
return IntPtrConstant(kSmiShiftSize + kSmiTagSize);
}
TNode<Int32T> SmiShiftBitsConstant32() {
return Int32Constant(kSmiShiftSize + kSmiTagSize);
}
// Emits keyed sloppy arguments load if the |value| is nullptr or store
// otherwise. Returns either the loaded value or |value|.
......
......@@ -1546,14 +1546,17 @@ const Operator* RepresentationChanger::TaggedSignedOperatorFor(
IrOpcode::Value opcode) {
switch (opcode) {
case IrOpcode::kSpeculativeNumberLessThan:
return machine()->Is32() ? machine()->Int32LessThan()
: machine()->Int64LessThan();
return (COMPRESS_POINTERS_BOOL || machine()->Is32())
? machine()->Int32LessThan()
: machine()->Int64LessThan();
case IrOpcode::kSpeculativeNumberLessThanOrEqual:
return machine()->Is32() ? machine()->Int32LessThanOrEqual()
: machine()->Int64LessThanOrEqual();
return (COMPRESS_POINTERS_BOOL || machine()->Is32())
? machine()->Int32LessThanOrEqual()
: machine()->Int64LessThanOrEqual();
case IrOpcode::kSpeculativeNumberEqual:
return machine()->Is32() ? machine()->Word32Equal()
: machine()->Word64Equal();
return (COMPRESS_POINTERS_BOOL || machine()->Is32())
? machine()->Word32Equal()
: machine()->Word64Equal();
default:
UNREACHABLE();
}
......
......@@ -1669,8 +1669,8 @@ DeoptimizationData OptimizedFrame::GetDeoptimizationData(
Object OptimizedFrame::receiver() const {
Code code = LookupCode();
if (code.kind() == Code::BUILTIN) {
Address argc_ptr = fp() + OptimizedBuiltinFrameConstants::kArgCOffset;
intptr_t argc = *reinterpret_cast<intptr_t*>(argc_ptr);
intptr_t argc = static_cast<int>(
Memory<intptr_t>(fp() + OptimizedBuiltinFrameConstants::kArgCOffset));
intptr_t args_size =
(StandardFrameConstants::kFixedSlotCountAboveFp + argc) *
kSystemPointerSize;
......
......@@ -82,7 +82,7 @@ TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase(
// Try to quickly handle the monomorphic case without knowing for sure
// if we have a weak reference in feedback.
GotoIf(IsNotWeakReferenceTo(feedback, receiver_map), if_miss);
GotoIfNot(IsWeakReferenceTo(feedback, receiver_map), if_miss);
TNode<MaybeObject> handler = UncheckedCast<MaybeObject>(
Load(MachineType::AnyTagged(), vector,
......@@ -117,7 +117,7 @@ void AccessorAssembler::HandlePolymorphicCase(
TNode<MaybeObject> maybe_cached_map =
LoadWeakFixedArrayElement(feedback, var_index.value());
CSA_ASSERT(this, IsWeakOrCleared(maybe_cached_map));
GotoIf(IsNotWeakReferenceTo(maybe_cached_map, receiver_map), &loop_next);
GotoIfNot(IsWeakReferenceTo(maybe_cached_map, receiver_map), &loop_next);
// Found, now call handler.
TNode<MaybeObject> handler =
......@@ -850,7 +850,7 @@ void AccessorAssembler::HandleLoadICProtoHandler(
Label load_from_cached_holder(this), is_smi(this), done(this);
GotoIf(TaggedIsSmi(maybe_holder_or_constant), &is_smi);
Branch(IsStrongReferenceTo(maybe_holder_or_constant, NullConstant()), &done,
Branch(TaggedEqual(maybe_holder_or_constant, NullConstant()), &done,
&load_from_cached_holder);
BIND(&is_smi);
......@@ -1192,13 +1192,13 @@ void AccessorAssembler::CheckFieldType(TNode<DescriptorArray> descriptors,
DCHECK_NE(static_cast<uint32_t>(kNoneType), kClearedWeakHeapObjectLower32);
DCHECK_NE(static_cast<uint32_t>(kAnyType), kClearedWeakHeapObjectLower32);
// FieldType::None can't hold any value.
GotoIf(WordEqual(BitcastMaybeObjectToWord(field_type),
IntPtrConstant(kNoneType)),
bailout);
GotoIf(
TaggedEqual(field_type, BitcastWordToTagged(IntPtrConstant(kNoneType))),
bailout);
// FieldType::Any can hold any value.
GotoIf(WordEqual(BitcastMaybeObjectToWord(field_type),
IntPtrConstant(kAnyType)),
&all_fine);
GotoIf(
TaggedEqual(field_type, BitcastWordToTagged(IntPtrConstant(kAnyType))),
&all_fine);
// Cleared weak references count as FieldType::None, which can't hold any
// value.
TNode<Map> field_type_map =
......
......@@ -834,7 +834,8 @@ TNode<Object> InterpreterAssembler::Construct(
// Check if we have monomorphic {new_target} feedback already.
TNode<MaybeObject> feedback =
LoadFeedbackVectorSlot(feedback_vector, slot_id);
Branch(IsWeakReferenceTo(feedback, new_target), &construct, &extra_checks);
Branch(IsWeakReferenceToObject(feedback, new_target), &construct,
&extra_checks);
BIND(&extra_checks);
{
......@@ -1016,7 +1017,8 @@ TNode<Object> InterpreterAssembler::ConstructWithSpread(
// Check if we have monomorphic {new_target} feedback already.
TNode<MaybeObject> feedback =
LoadFeedbackVectorSlot(feedback_vector, slot_id);
Branch(IsWeakReferenceTo(feedback, new_target), &construct, &extra_checks);
Branch(IsWeakReferenceToObject(feedback, new_target), &construct,
&extra_checks);
BIND(&extra_checks);
{
......
......@@ -176,7 +176,8 @@ bool PartialSerializer::SerializeJSObjectWithEmbedderFields(Object obj) {
} else {
// If no serializer is provided and the field was empty, we serialize it
// by default to nullptr.
if (serialize_embedder_fields_.callback == nullptr && object.ptr() == 0) {
if (serialize_embedder_fields_.callback == nullptr &&
object == Smi::zero()) {
serialized_data.push_back({nullptr, 0});
} else {
DCHECK_NOT_NULL(serialize_embedder_fields_.callback);
......
......@@ -10,9 +10,10 @@
#include "src/base/ieee754.h"
#include "src/base/overflowing-math.h"
#include "src/base/utils/random-number-generator.h"
#include "src/common/ptr-compr-inl.h"
#include "src/objects/objects-inl.h"
#include "src/utils/boxed-float.h"
#include "src/utils/utils.h"
#include "src/objects/objects-inl.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
#include "test/cctest/compiler/value-helper.h"
......@@ -410,11 +411,12 @@ TEST(CompressDecompressTaggedAnyPointer) {
}
TEST(CompressDecompressTaggedAnySigned) {
RawMachineAssemblerTester<int64_t> m;
RawMachineAssemblerTester<Address> m;
Smi smi = Smi::FromInt(123);
int64_t smiPointer = static_cast<int64_t>(smi.ptr());
Node* node = m.Int64Constant(smiPointer);
Node* node = m.Int64Constant(static_cast<int64_t>(smi.ptr()));
m.Return(m.ChangeCompressedToTagged(m.ChangeTaggedToCompressed(node)));
Address smiPointer =
DecompressTaggedAny(m.isolate(), CompressTagged(smi.ptr()));
CHECK_EQ(smiPointer, m.Call());
}
......
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