[csa] Add TNode<MaybeObject>.

LoadMaybeWeakField returns a TNode<MaybeObject>, and the only way to extract
values from it is through explicit functions.

BUG=v8:7308

Change-Id: I98da6b715527bb9976b4c78ed9caaa39fbcb3ed5
Reviewed-on: https://chromium-review.googlesource.com/1014106
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52732}
This commit is contained in:
Marja Hölttä 2018-04-23 16:10:06 +02:00 committed by Commit Bot
parent 5c9b30ae38
commit c823ca959e
9 changed files with 121 additions and 49 deletions

View File

@ -829,6 +829,12 @@ TNode<BoolT> CodeStubAssembler::TaggedIsSmi(SloppyTNode<Object> a) {
IntPtrConstant(0));
}
TNode<BoolT> CodeStubAssembler::TaggedIsSmi(TNode<MaybeObject> a) {
return WordEqual(
WordAnd(BitcastMaybeObjectToWord(a), IntPtrConstant(kSmiTagMask)),
IntPtrConstant(0));
}
TNode<BoolT> CodeStubAssembler::TaggedIsNotSmi(SloppyTNode<Object> a) {
return WordNotEqual(
WordAnd(BitcastTaggedToWord(a), IntPtrConstant(kSmiTagMask)),
@ -1492,15 +1498,15 @@ TNode<PrototypeInfo> CodeStubAssembler::LoadMapPrototypeInfo(
SloppyTNode<Map> map, Label* if_no_proto_info) {
Label if_strong_heap_object(this);
CSA_ASSERT(this, IsMap(map));
Node* maybe_prototype_info =
LoadObjectField(map, Map::kTransitionsOrPrototypeInfoOffset);
VARIABLE(prototype_info, MachineRepresentation::kTagged);
TNode<MaybeObject> maybe_prototype_info =
LoadMaybeWeakObjectField(map, Map::kTransitionsOrPrototypeInfoOffset);
TVARIABLE(Object, prototype_info);
DispatchMaybeObject(maybe_prototype_info, if_no_proto_info, if_no_proto_info,
if_no_proto_info, &if_strong_heap_object,
&prototype_info);
BIND(&if_strong_heap_object);
GotoIfNot(WordEqual(LoadMap(prototype_info.value()),
GotoIfNot(WordEqual(LoadMap(CAST(prototype_info.value())),
LoadRoot(Heap::kPrototypeInfoMapRootIndex)),
if_no_proto_info);
return CAST(prototype_info.value());
@ -1681,49 +1687,62 @@ TNode<Object> CodeStubAssembler::LoadWeakCellValue(
return value;
}
void CodeStubAssembler::DispatchMaybeObject(Node* maybe_object, Label* if_smi,
Label* if_cleared, Label* if_weak,
Label* if_strong,
Variable* extracted) {
void CodeStubAssembler::DispatchMaybeObject(TNode<MaybeObject> maybe_object,
Label* if_smi, Label* if_cleared,
Label* if_weak, Label* if_strong,
TVariable<Object>* extracted) {
Label inner_if_smi(this), inner_if_strong(this);
GotoIf(TaggedIsSmi(maybe_object), &inner_if_smi);
GotoIf(WordEqual(maybe_object, IntPtrConstant(reinterpret_cast<intptr_t>(
HeapObjectReference::ClearedValue()))),
GotoIf(WordEqual(BitcastMaybeObjectToWord(maybe_object),
IntPtrConstant(reinterpret_cast<intptr_t>(
HeapObjectReference::ClearedValue()))),
if_cleared);
GotoIf(WordEqual(WordAnd(BitcastTaggedToWord(maybe_object),
GotoIf(WordEqual(WordAnd(BitcastMaybeObjectToWord(maybe_object),
IntPtrConstant(kWeakHeapObjectMask)),
IntPtrConstant(0)),
&inner_if_strong);
extracted->Bind(
BitcastWordToTagged(WordAnd(BitcastTaggedToWord(maybe_object),
IntPtrConstant(~kWeakHeapObjectMask))));
*extracted =
BitcastWordToTagged(WordAnd(BitcastMaybeObjectToWord(maybe_object),
IntPtrConstant(~kWeakHeapObjectMask)));
Goto(if_weak);
BIND(&inner_if_smi);
extracted->Bind(maybe_object);
*extracted = ToStrongHeapObjectOrSmi(maybe_object);
Goto(if_smi);
BIND(&inner_if_strong);
extracted->Bind(maybe_object);
*extracted = ToStrongHeapObject(maybe_object);
Goto(if_strong);
}
Node* CodeStubAssembler::IsStrongHeapObject(Node* value) {
return WordEqual(
WordAnd(BitcastTaggedToWord(value), IntPtrConstant(kWeakHeapObjectMask)),
IntPtrConstant(0));
TNode<BoolT> CodeStubAssembler::IsStrongHeapObject(TNode<MaybeObject> value) {
return WordEqual(WordAnd(BitcastMaybeObjectToWord(value),
IntPtrConstant(kWeakHeapObjectMask)),
IntPtrConstant(0));
}
Node* CodeStubAssembler::ToStrongHeapObject(Node* value) {
return BitcastWordToTagged(WordAnd(BitcastTaggedToWord(value),
IntPtrConstant(~kWeakHeapObjectMask)));
TNode<HeapObject> CodeStubAssembler::GetHeapObject(TNode<MaybeObject> value) {
return UncheckedCast<HeapObject>(BitcastWordToTagged(WordAnd(
BitcastMaybeObjectToWord(value), IntPtrConstant(~kWeakHeapObjectMask))));
}
TNode<Object> CodeStubAssembler::LoadArrayElement(
TNode<HeapObject> CodeStubAssembler::ToStrongHeapObject(
TNode<MaybeObject> value) {
AssertIsStrongHeapObject(value);
return ReinterpretCast<HeapObject>(value);
}
TNode<Object> CodeStubAssembler::ToStrongHeapObjectOrSmi(
TNode<MaybeObject> value) {
AssertIsStrongHeapObjectOrSmi(value);
return ReinterpretCast<Object>(value);
}
TNode<MaybeObject> CodeStubAssembler::LoadArrayElement(
SloppyTNode<Object> object, int array_header_size, Node* index_node,
int additional_offset, ParameterMode parameter_mode,
LoadSensitivity needs_poisoning) {
@ -1733,7 +1752,7 @@ TNode<Object> CodeStubAssembler::LoadArrayElement(
int32_t header_size = array_header_size + additional_offset - kHeapObjectTag;
TNode<IntPtrT> offset = ElementOffsetFromIndex(index_node, HOLEY_ELEMENTS,
parameter_mode, header_size);
return UncheckedCast<Object>(
return UncheckedCast<MaybeObject>(
Load(MachineType::AnyTagged(), object, offset, needs_poisoning));
}
@ -1744,8 +1763,9 @@ TNode<Object> CodeStubAssembler::LoadFixedArrayElement(
// and thus the reasonable assert IsFixedArraySubclass(object) is
// untrue. TODO(marja): Fix.
CSA_SLOW_ASSERT(this, IsNotWeakFixedArraySubclass(object));
return LoadArrayElement(object, FixedArray::kHeaderSize, index_node,
additional_offset, parameter_mode, needs_poisoning);
return ToStrongHeapObjectOrSmi(
LoadArrayElement(object, FixedArray::kHeaderSize, index_node,
additional_offset, parameter_mode, needs_poisoning));
}
TNode<RawPtrT> CodeStubAssembler::LoadFixedTypedArrayBackingStore(
@ -6943,9 +6963,8 @@ void CodeStubAssembler::LookupLinear(TNode<Name> unique_name,
BuildFastLoop(last_exclusive, first_inclusive,
[=](SloppyTNode<IntPtrT> name_index) {
TNode<Name> candidate_name = CAST(
LoadArrayElement(array, Array::kHeaderSize, name_index));
CSA_ASSERT(this, IsStrongHeapObject(candidate_name));
TNode<Name> candidate_name = CAST(ToStrongHeapObject(
LoadArrayElement(array, Array::kHeaderSize, name_index)));
*var_name_index = name_index;
GotoIf(WordEqual(candidate_name, unique_name), if_found);
},
@ -7014,10 +7033,9 @@ TNode<Name> CodeStubAssembler::GetKey(TNode<Array> array,
std::is_base_of<TransitionArray, Array>::value,
"T must be a descendant of FixedArray or a TransitionArray");
const int key_offset = Array::ToKeyIndex(0) * kPointerSize;
TNode<Name> key =
CAST(LoadArrayElement(array, Array::kHeaderSize,
EntryIndexToIndex<Array>(entry_index), key_offset));
CSA_ASSERT(this, IsStrongHeapObject(key));
TNode<Name> key = CAST(ToStrongHeapObject(
LoadArrayElement(array, Array::kHeaderSize,
EntryIndexToIndex<Array>(entry_index), key_offset)));
return key;
}
@ -11442,6 +11460,20 @@ void CodeStubAssembler::InitializeFunctionContext(Node* native_context,
native_context);
}
void CodeStubAssembler::AssertIsStrongHeapObject(
SloppyTNode<MaybeObject> object) {
CSA_SLOW_ASSERT(this, WordEqual(WordAnd(BitcastMaybeObjectToWord(object),
IntPtrConstant(kHeapObjectTagMask)),
IntPtrConstant(kHeapObjectTag)));
}
void CodeStubAssembler::AssertIsStrongHeapObjectOrSmi(
SloppyTNode<MaybeObject> object) {
CSA_SLOW_ASSERT(this, WordEqual(WordAnd(BitcastMaybeObjectToWord(object),
IntPtrConstant(kWeakHeapObjectMask)),
IntPtrConstant(0)));
}
void CodeStubAssembler::AssertIsStrongHeapObject(
SloppyTNode<HeapObject> object) {
CSA_SLOW_ASSERT(this, WordEqual(WordAnd(BitcastTaggedToWord(object),

View File

@ -436,6 +436,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Check a value for smi-ness
TNode<BoolT> TaggedIsSmi(SloppyTNode<Object> a);
TNode<BoolT> TaggedIsSmi(TNode<MaybeObject> a);
TNode<BoolT> TaggedIsNotSmi(SloppyTNode<Object> a);
// Check that the value is a non-negative smi.
TNode<BoolT> TaggedIsPositiveSmi(SloppyTNode<Object> a);
@ -537,6 +538,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Load a SMI root, untag it, and convert to Word32.
Node* LoadAndUntagToWord32Root(Heap::RootListIndex root_index);
TNode<MaybeObject> LoadMaybeWeakObjectField(SloppyTNode<HeapObject> object,
int offset) {
return UncheckedCast<MaybeObject>(
LoadObjectField(object, offset, MachineType::AnyTagged()));
}
// Tag a smi and store it.
Node* StoreAndTagSmi(Node* base, int offset, Node* value);
@ -647,14 +654,16 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// pointed to)
// - a strong reference (jump to "if_strong", "extracted" will be the object
// pointed to)
void DispatchMaybeObject(Node* maybe_object, Label* if_smi, Label* if_cleared,
Label* if_weak, Label* if_strong,
Variable* extracted);
Node* IsStrongHeapObject(Node* value);
Node* ToStrongHeapObject(Node* value);
void DispatchMaybeObject(TNode<MaybeObject> maybe_object, Label* if_smi,
Label* if_cleared, Label* if_weak, Label* if_strong,
TVariable<Object>* extracted);
TNode<BoolT> IsStrongHeapObject(TNode<MaybeObject> value);
TNode<HeapObject> GetHeapObject(TNode<MaybeObject> value);
TNode<HeapObject> ToStrongHeapObject(TNode<MaybeObject> value);
TNode<Object> ToStrongHeapObjectOrSmi(TNode<MaybeObject> value);
// Load an array element from a FixedArray / WeakFixedArray.
TNode<Object> LoadArrayElement(
TNode<MaybeObject> LoadArrayElement(
SloppyTNode<Object> object, int array_header_size, Node* index,
int additional_offset = 0,
ParameterMode parameter_mode = INTPTR_PARAMETERS,
@ -2290,6 +2299,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
void InitializeFunctionContext(Node* native_context, Node* context,
int slots);
void AssertIsStrongHeapObject(SloppyTNode<MaybeObject> object);
void AssertIsStrongHeapObjectOrSmi(SloppyTNode<MaybeObject> object);
void AssertIsStrongHeapObject(SloppyTNode<HeapObject> object);
private:

View File

@ -19,6 +19,7 @@
#include "src/machine-type.h"
#include "src/objects/data-handler.h"
#include "src/objects/map.h"
#include "src/objects/maybe-object.h"
#include "src/runtime/runtime.h"
#include "src/zone/zone-containers.h"
@ -156,8 +157,10 @@ template <class T>
struct is_valid_type_tag {
static const bool value = std::is_base_of<Object, T>::value ||
std::is_base_of<UntaggedT, T>::value ||
std::is_base_of<MaybeObject, T>::value ||
std::is_same<ExternalReference, T>::value;
static const bool is_tagged = std::is_base_of<Object, T>::value;
static const bool is_tagged = std::is_base_of<Object, T>::value ||
std::is_base_of<MaybeObject, T>::value;
};
template <class T1, class T2>
@ -485,6 +488,7 @@ TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
V(Float64ExtractLowWord32, Word32T, Float64T) \
V(Float64ExtractHighWord32, Word32T, Float64T) \
V(BitcastTaggedToWord, IntPtrT, Object) \
V(BitcastMaybeObjectToWord, IntPtrT, MaybeObject) \
V(BitcastWordToTagged, Object, WordT) \
V(BitcastWordToTaggedSigned, Smi, WordT) \
V(TruncateFloat64ToFloat32, Float32T, Float64T) \

View File

@ -701,6 +701,14 @@ struct MachineOperatorGlobalCache {
};
BitcastTaggedToWordOperator kBitcastTaggedToWord;
struct BitcastMaybeObjectToWordOperator : public Operator {
BitcastMaybeObjectToWordOperator()
: Operator(IrOpcode::kBitcastTaggedToWord,
Operator::kEliminatable | Operator::kNoWrite,
"BitcastMaybeObjectToWord", 1, 1, 1, 1, 1, 0) {}
};
BitcastMaybeObjectToWordOperator kBitcastMaybeObjectToWord;
struct PoisonOnSpeculationTagged : public Operator {
PoisonOnSpeculationTagged()
: Operator(IrOpcode::kPoisonOnSpeculationTagged,
@ -912,6 +920,10 @@ const Operator* MachineOperatorBuilder::BitcastTaggedToWord() {
return &cache_.kBitcastTaggedToWord;
}
const Operator* MachineOperatorBuilder::BitcastMaybeObjectToWord() {
return &cache_.kBitcastMaybeObjectToWord;
}
const Operator* MachineOperatorBuilder::DebugAbort() {
return &cache_.kDebugAbort;
}

View File

@ -301,6 +301,10 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
// This operator reinterprets the bits of a tagged pointer as word.
const Operator* BitcastTaggedToWord();
// This operator reinterprets the bits of a tagged MaybeObject pointer as
// word.
const Operator* BitcastMaybeObjectToWord();
// This operator reinterprets the bits of a word as tagged pointer.
const Operator* BitcastWordToTagged();

View File

@ -578,6 +578,13 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
return AddNode(machine()->BitcastTaggedToWord(), a);
#else
return a;
#endif
}
Node* BitcastMaybeObjectToWord(Node* a) {
#ifdef ENABLE_VERIFY_CSA
return AddNode(machine()->BitcastMaybeObjectToWord(), a);
#else
return a;
#endif
}
Node* BitcastWordToTagged(Node* a) {

View File

@ -684,14 +684,14 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
TVARIABLE(Map, var_transition_map);
Label simple_transition(this), transition_array(this),
found_handler_candidate(this);
TNode<Object> maybe_handler =
LoadObjectField(receiver_map, Map::kTransitionsOrPrototypeInfoOffset);
TNode<MaybeObject> maybe_handler = LoadMaybeWeakObjectField(
receiver_map, Map::kTransitionsOrPrototypeInfoOffset);
// SMI -> slow
// cleared weak reference -> slow
// weak reference -> simple_transition
// strong reference -> transition_array
VARIABLE(var_transition_map_or_array, MachineRepresentation::kTagged);
TVARIABLE(Object, var_transition_map_or_array);
DispatchMaybeObject(maybe_handler, slow, slow, &simple_transition,
&transition_array, &var_transition_map_or_array);
@ -732,7 +732,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
const int kKeyToTargetOffset = (TransitionArray::kEntryTargetIndex -
TransitionArray::kEntryKeyIndex) *
kPointerSize;
var_transition_map = CAST(ToStrongHeapObject(
var_transition_map = CAST(GetHeapObject(
LoadArrayElement(transitions, WeakFixedArray::kHeaderSize,
var_name_index.value(), kKeyToTargetOffset)));
Goto(&found_handler_candidate);

View File

@ -91,6 +91,11 @@ HeapObject* MaybeObject::GetHeapObject() {
return RemoveWeakHeapObjectMask(reinterpret_cast<HeapObjectReference*>(this));
}
MaybeObject* MaybeObject::MakeWeak(MaybeObject* object) {
DCHECK(object->IsStrongOrWeakHeapObject());
return AddWeakHeapObjectMask(object);
}
} // namespace internal
} // namespace v8

View File

@ -50,10 +50,7 @@ class MaybeObject {
return reinterpret_cast<MaybeObject*>(object);
}
static MaybeObject* MakeWeak(MaybeObject* object) {
DCHECK(object->IsStrongOrWeakHeapObject());
return AddWeakHeapObjectMask(object);
}
static inline MaybeObject* MakeWeak(MaybeObject* object);
#ifdef VERIFY_HEAP
static void VerifyMaybeObjectPointer(MaybeObject* p);