[in-place weak refs] Make it possible to CAST to TNode<Object/HeapObject>.

BUG=v8:7308

Change-Id: I04c21ed1919f9bc9c68312c15d1e1229aaba32b5
Reviewed-on: https://chromium-review.googlesource.com/1061013
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53301}
This commit is contained in:
Marja Hölttä 2018-05-23 13:19:44 +02:00 committed by Commit Bot
parent d2234d5a3d
commit f3d9f71df1
8 changed files with 78 additions and 94 deletions

View File

@ -308,8 +308,8 @@ Node* ConstructorBuiltinsAssembler::EmitCreateRegExpLiteral(
Label call_runtime(this, Label::kDeferred), end(this);
VARIABLE(result, MachineRepresentation::kTagged);
TNode<Object> literal_site = ToObject(
LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
TNode<Object> literal_site =
CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
GotoIf(NotHasBoilerplate(literal_site), &call_runtime);
{
Node* boilerplate = literal_site;
@ -353,8 +353,8 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowArrayLiteral(
return_result(this);
VARIABLE(result, MachineRepresentation::kTagged);
TNode<Object> allocation_site = ToObject(
LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
TNode<Object> allocation_site =
CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
GotoIf(NotHasBoilerplate(allocation_site), call_runtime);
Node* boilerplate = LoadAllocationSiteBoilerplate(allocation_site);
@ -393,8 +393,8 @@ Node* ConstructorBuiltinsAssembler::EmitCreateEmptyArrayLiteral(
// Array literals always have a valid AllocationSite to properly track
// elements transitions.
TVARIABLE(Object, allocation_site,
ToObject(LoadFeedbackVectorSlot(feedback_vector, slot, 0,
INTPTR_PARAMETERS)));
CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0,
INTPTR_PARAMETERS)));
Label create_empty_array(this),
initialize_allocation_site(this, Label::kDeferred), done(this);
@ -440,8 +440,8 @@ TF_BUILTIN(CreateEmptyArrayLiteral, ConstructorBuiltinsAssembler) {
Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral(
Node* feedback_vector, Node* slot, Label* call_runtime) {
TNode<Object> allocation_site = ToObject(
LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
TNode<Object> allocation_site =
CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
GotoIf(NotHasBoilerplate(allocation_site), call_runtime);
Node* boilerplate = LoadAllocationSiteBoilerplate(allocation_site);

View File

@ -1720,11 +1720,11 @@ void CodeStubAssembler::DispatchMaybeObject(TNode<MaybeObject> maybe_object,
Goto(if_weak);
BIND(&inner_if_smi);
*extracted = ToObject(maybe_object);
*extracted = CAST(maybe_object);
Goto(if_smi);
BIND(&inner_if_strong);
*extracted = ToObject(maybe_object);
*extracted = CAST(maybe_object);
Goto(if_strong);
}
@ -1734,16 +1734,10 @@ TNode<BoolT> CodeStubAssembler::IsStrongHeapObject(TNode<MaybeObject> value) {
IntPtrConstant(kHeapObjectTag));
}
TNode<HeapObject> CodeStubAssembler::ToStrongHeapObject(
TNode<MaybeObject> value) {
CSA_ASSERT(this, IsStrongHeapObject(value));
return ReinterpretCast<HeapObject>(value);
}
TNode<HeapObject> CodeStubAssembler::ToStrongHeapObject(
TNode<MaybeObject> value, Label* if_not_strong) {
GotoIfNot(IsStrongHeapObject(value), if_not_strong);
return ToStrongHeapObject(value);
return CAST(value);
}
TNode<BoolT> CodeStubAssembler::IsWeakOrClearedHeapObject(
@ -1793,19 +1787,6 @@ TNode<BoolT> CodeStubAssembler::IsNotWeakReferenceTo(TNode<MaybeObject> object,
BitcastTaggedToWord(value));
}
TNode<BoolT> CodeStubAssembler::IsObject(TNode<MaybeObject> value) {
return WordNotEqual(WordAnd(BitcastMaybeObjectToWord(value),
IntPtrConstant(kHeapObjectTagMask)),
IntPtrConstant(kWeakHeapObjectTag));
}
TNode<Object> CodeStubAssembler::ToObject(TNode<MaybeObject> value) {
// TODO(marja): Make CAST work (with the appropriate check); replace this with
// CAST.
CSA_ASSERT(this, IsObject(value));
return ReinterpretCast<Object>(value);
}
TNode<MaybeObject> CodeStubAssembler::MakeWeak(TNode<HeapObject> value) {
return ReinterpretCast<MaybeObject>(BitcastWordToTagged(
WordOr(BitcastTaggedToWord(value), IntPtrConstant(kWeakHeapObjectTag))));
@ -1858,8 +1839,7 @@ TNode<Object> CodeStubAssembler::LoadFixedArrayElement(
TNode<MaybeObject> element =
LoadArrayElement(object, FixedArray::kHeaderSize, index_node,
additional_offset, parameter_mode, needs_poisoning);
CSA_ASSERT(this, IsObject(element));
return ToObject(element);
return CAST(element);
}
TNode<Object> CodeStubAssembler::LoadPropertyArrayElement(
@ -1869,9 +1849,9 @@ TNode<Object> CodeStubAssembler::LoadPropertyArrayElement(
LoadSensitivity needs_poisoning = LoadSensitivity::kSafe;
STATIC_ASSERT(PropertyArray::kHeaderSize == FixedArray::kHeaderSize);
return ToObject(LoadArrayElement(object, PropertyArray::kHeaderSize, index,
additional_offset, parameter_mode,
needs_poisoning));
return CAST(LoadArrayElement(object, PropertyArray::kHeaderSize, index,
additional_offset, parameter_mode,
needs_poisoning));
}
TNode<RawPtrT> CodeStubAssembler::LoadFixedTypedArrayBackingStore(
@ -7293,9 +7273,7 @@ void CodeStubAssembler::LookupLinear(TNode<Name> unique_name,
[=](SloppyTNode<IntPtrT> name_index) {
TNode<MaybeObject> element =
LoadArrayElement(array, Array::kHeaderSize, name_index);
CSA_ASSERT(this, IsStrongHeapObject(element));
TNode<Name> candidate_name =
CAST(ToStrongHeapObject(element));
TNode<Name> candidate_name = CAST(element);
*var_name_index = name_index;
GotoIf(WordEqual(candidate_name, unique_name), if_found);
},
@ -7367,8 +7345,7 @@ TNode<Name> CodeStubAssembler::GetKey(TNode<Array> array,
TNode<MaybeObject> element =
LoadArrayElement(array, Array::kHeaderSize,
EntryIndexToIndex<Array>(entry_index), key_offset);
CSA_ASSERT(this, IsStrongHeapObject(element));
return CAST(ToStrongHeapObject(element));
return CAST(element);
}
template TNode<Name> CodeStubAssembler::GetKey<DescriptorArray>(
@ -8432,8 +8409,7 @@ void CodeStubAssembler::UpdateFeedback(Node* feedback, Node* feedback_vector,
// our new feedback in place.
TNode<MaybeObject> feedback_element =
LoadFeedbackVectorSlot(feedback_vector, slot_id);
CSA_ASSERT(this, IsObject(feedback_element));
TNode<Smi> previous_feedback = CAST(ToObject(feedback_element));
TNode<Smi> previous_feedback = CAST(feedback_element);
TNode<Smi> combined_feedback = SmiOr(previous_feedback, CAST(feedback));
Label end(this);

View File

@ -678,7 +678,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<BoolT> IsStrongHeapObject(TNode<Object> value) {
return IsStrongHeapObject(ReinterpretCast<MaybeObject>(value));
}
TNode<HeapObject> ToStrongHeapObject(TNode<MaybeObject> value);
TNode<HeapObject> ToStrongHeapObject(TNode<MaybeObject> value,
Label* if_not_strong);
@ -697,14 +696,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<BoolT> IsNotWeakReferenceTo(TNode<MaybeObject> object,
TNode<Object> value);
// IsObject == true when the MaybeObject is a strong HeapObject or a smi.
TNode<BoolT> IsObject(TNode<MaybeObject> value);
// This variant is for overzealous checking.
TNode<BoolT> IsObject(TNode<Object> value) {
return IsObject(ReinterpretCast<MaybeObject>(value));
}
TNode<Object> ToObject(TNode<MaybeObject> value);
TNode<MaybeObject> MakeWeak(TNode<HeapObject> value);
// Load an array element from a FixedArray / WeakFixedArray / PropertyArray.

View File

@ -244,6 +244,21 @@ bool CodeAssembler::IsIntPtrAbsWithOverflowSupported() const {
: IsInt32AbsWithOverflowSupported();
}
#ifdef DEBUG
void CodeAssembler::GenerateCheckMaybeObjectIsObject(Node* node,
const char* location) {
Label ok(this);
GotoIf(WordNotEqual(WordAnd(BitcastMaybeObjectToWord(node),
IntPtrConstant(kHeapObjectTagMask)),
IntPtrConstant(kWeakHeapObjectTag)),
&ok);
Node* message_node = StringConstant(location);
DebugAbort(message_node);
Unreachable();
Bind(&ok);
}
#endif
#ifdef V8_EMBEDDED_BUILTINS
TNode<HeapObject> CodeAssembler::LookupConstant(Handle<HeapObject> object) {
DCHECK(isolate()->ShouldLoadConstantsFromRootList());

View File

@ -35,6 +35,7 @@ class JSRegExpStringIterator;
class JSWeakCollection;
class JSWeakMap;
class JSWeakSet;
class MaybeObject;
class PromiseCapability;
class PromiseFulfillReactionJobTask;
class PromiseReaction;
@ -361,6 +362,16 @@ struct types_have_common_values<UnionT<T1, T2>, UnionT<U1, U2>> {
types_have_common_values<T2, U2>::value;
};
template <class T>
struct types_have_common_values<T, MaybeObject> {
static const bool value = types_have_common_values<T, Object>::value;
};
template <class T>
struct types_have_common_values<MaybeObject, T> {
static const bool value = types_have_common_values<Object, T>::value;
};
// TNode<T> is an SSA value with the static type tag T, which is one of the
// following:
// - a subclass of internal::Object represents a tagged type
@ -592,6 +603,10 @@ class V8_EXPORT_PRIVATE CodeAssembler {
template <class A>
operator TNode<A>() {
static_assert(
!std::is_same<A, MaybeObject>::value,
"Can't cast to MaybeObject, use explicit conversion functions. ");
static_assert(types_have_common_values<A, PreviousType>::value,
"Incompatible types: this cast can never succeed.");
static_assert(std::is_convertible<TNode<A>, TNode<Object>>::value,
@ -603,6 +618,9 @@ class V8_EXPORT_PRIVATE CodeAssembler {
"Unnecessary CAST: types are convertible.");
#ifdef DEBUG
if (FLAG_debug_code) {
if (std::is_same<PreviousType, MaybeObject>::value) {
code_assembler_->GenerateCheckMaybeObjectIsObject(node_, location_);
}
Node* function = code_assembler_->ExternalConstant(
ExternalReference::check_object_type());
code_assembler_->CallCFunction3(
@ -668,6 +686,10 @@ class V8_EXPORT_PRIVATE CodeAssembler {
#define CAST(x) Cast(x, "")
#endif
#ifdef DEBUG
void GenerateCheckMaybeObjectIsObject(Node* node, const char* location);
#endif
#ifdef V8_EMBEDDED_BUILTINS
TNode<HeapObject> LookupConstant(Handle<HeapObject> object);
TNode<ExternalReference> LookupExternalReference(ExternalReference reference);

View File

@ -172,7 +172,6 @@ void AccessorAssembler::HandleLoadICHandlerCase(
ExitPoint* exit_point, ICMode ic_mode, OnNonExistent on_nonexistent,
ElementSupport support_elements) {
Comment("have_handler");
CSA_ASSERT(this, IsObject(handler));
VARIABLE(var_holder, MachineRepresentation::kTagged, p->holder);
VARIABLE(var_smi_handler, MachineRepresentation::kTagged, handler);
@ -800,8 +799,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
BIND(&if_smi_handler);
{
Node* holder = p->receiver;
CSA_ASSERT(this, IsObject(handler));
Node* handler_word = SmiUntag(CAST(ToObject(handler)));
Node* handler_word = SmiUntag(CAST(handler));
Label if_fast_smi(this), if_proxy(this);
@ -867,8 +865,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
BIND(&if_nonsmi_handler);
{
GotoIf(IsWeakOrClearedHeapObject(handler), &store_transition_or_global);
CSA_ASSERT(this, IsStrongHeapObject(handler));
TNode<HeapObject> strong_handler = ToStrongHeapObject(handler);
TNode<HeapObject> strong_handler = CAST(handler);
TNode<Map> handler_map = LoadMap(strong_handler);
Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler);
@ -2349,9 +2346,7 @@ void AccessorAssembler::LoadIC_BytecodeHandler(const LoadICParameters* p,
&var_handler, &try_polymorphic);
BIND(&if_handler);
CSA_ASSERT(this, IsObject(var_handler.value()));
HandleLoadICHandlerCase(p, ToObject(var_handler.value()), &miss,
exit_point);
HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, exit_point);
BIND(&try_polymorphic);
{
@ -2400,9 +2395,7 @@ void AccessorAssembler::LoadIC(const LoadICParameters* p) {
TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
&var_handler, &try_polymorphic);
BIND(&if_handler);
CSA_ASSERT(this, IsObject(var_handler.value()));
HandleLoadICHandlerCase(p, ToObject(var_handler.value()), &miss,
&direct_exit);
HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, &direct_exit);
BIND(&try_polymorphic);
TNode<HeapObject> strong_feedback = ToStrongHeapObject(feedback, &miss);
@ -2559,8 +2552,7 @@ void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase(
BIND(&if_lexical_var);
{
Comment("Load lexical variable");
CSA_ASSERT(this, IsObject(maybe_weak_ref));
TNode<IntPtrT> lexical_handler = SmiUntag(CAST(ToObject(maybe_weak_ref)));
TNode<IntPtrT> lexical_handler = SmiUntag(CAST(maybe_weak_ref));
TNode<IntPtrT> context_index =
Signed(DecodeWord<FeedbackNexus::ContextIndexBits>(lexical_handler));
TNode<IntPtrT> slot_index =
@ -2583,8 +2575,7 @@ void AccessorAssembler::LoadGlobalIC_TryHandlerCase(
TNode<MaybeObject> feedback_element =
LoadFeedbackVectorSlot(vector, slot, kPointerSize, slot_mode);
CSA_ASSERT(this, IsObject(feedback_element));
TNode<Object> handler = ToObject(feedback_element);
TNode<Object> handler = CAST(feedback_element);
GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
miss);
@ -2623,9 +2614,8 @@ void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) {
&var_handler, &try_polymorphic);
BIND(&if_handler);
{
CSA_ASSERT(this, IsObject(var_handler.value()));
HandleLoadICHandlerCase(p, ToObject(var_handler.value()), &miss,
&direct_exit, ICMode::kNonGlobalIC,
HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, &direct_exit,
ICMode::kNonGlobalIC,
OnNonExistent::kReturnUndefined, kSupportElements);
}
@ -2784,25 +2774,21 @@ void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p) {
// LoadIC handler logic below.
CSA_ASSERT(this, IsName(name));
CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map)));
CSA_ASSERT(this, IsStrongHeapObject(LoadFeedbackVectorSlot(vector, slot, 0,
SMI_PARAMETERS)));
CSA_ASSERT(this, WordEqual(name, ToStrongHeapObject(LoadFeedbackVectorSlot(
CSA_ASSERT(this, WordEqual(name, CAST(LoadFeedbackVectorSlot(
vector, slot, 0, SMI_PARAMETERS))));
// Check if we have a matching handler for the {receiver_map}.
TNode<MaybeObject> feedback_element =
LoadFeedbackVectorSlot(vector, slot, kPointerSize, SMI_PARAMETERS);
CSA_ASSERT(this, IsObject(feedback_element));
TNode<WeakFixedArray> array = CAST(ToObject(feedback_element));
TNode<WeakFixedArray> array = CAST(feedback_element);
HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss,
1);
BIND(&if_handler);
{
ExitPoint direct_exit(this);
CSA_ASSERT(this, IsObject(var_handler.value()));
HandleLoadICHandlerCase(p, ToObject(var_handler.value()), &miss,
&direct_exit, ICMode::kNonGlobalIC,
HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, &direct_exit,
ICMode::kNonGlobalIC,
OnNonExistent::kReturnUndefined, kOnlyProperties);
}
@ -2866,8 +2852,7 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
Comment("StoreIC_if_handler_from_stub_cache");
GotoIf(TaggedIsSmi(var_handler.value()), &if_handler);
CSA_ASSERT(this, IsStrongHeapObject(var_handler.value()));
TNode<HeapObject> handler = ToStrongHeapObject(var_handler.value());
TNode<HeapObject> handler = CAST(var_handler.value());
GotoIfNot(IsWeakCell(handler), &if_handler);
TNode<HeapObject> value = CAST(LoadWeakCellValue(CAST(handler), &miss));
@ -2939,8 +2924,7 @@ void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) {
BIND(&if_lexical_var);
{
Comment("Store lexical variable");
CSA_ASSERT(this, IsObject(maybe_weak_ref));
TNode<IntPtrT> lexical_handler = SmiUntag(CAST(ToObject(maybe_weak_ref)));
TNode<IntPtrT> lexical_handler = SmiUntag(CAST(maybe_weak_ref));
TNode<IntPtrT> context_index =
Signed(DecodeWord<FeedbackNexus::ContextIndexBits>(lexical_handler));
TNode<IntPtrT> slot_index =
@ -3071,8 +3055,7 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) {
// with at least one map/handler pair.
TNode<MaybeObject> feedback_element = LoadFeedbackVectorSlot(
p->vector, p->slot, kPointerSize, SMI_PARAMETERS);
CSA_ASSERT(this, IsObject(feedback_element));
TNode<WeakFixedArray> array = CAST(ToObject(feedback_element));
TNode<WeakFixedArray> array = CAST(feedback_element);
HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler,
&miss, 1);
}
@ -3105,8 +3088,7 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
Comment("StoreInArrayLiteralIC_if_handler");
// This is a stripped-down version of HandleStoreICHandlerCase.
CSA_ASSERT(this, IsStrongHeapObject(var_handler.value()));
TNode<HeapObject> handler = ToStrongHeapObject(var_handler.value());
TNode<HeapObject> handler = CAST(var_handler.value());
Label if_transitioning_element_store(this);
GotoIfNot(IsCode(handler), &if_transitioning_element_store);
StoreWithVectorDescriptor descriptor(isolate());
@ -3194,8 +3176,7 @@ void AccessorAssembler::GenerateLoadIC_Noninlined() {
Node* receiver_map = LoadReceiverMap(receiver);
TNode<MaybeObject> feedback_element =
LoadFeedbackVectorSlot(vector, slot, 0, SMI_PARAMETERS);
CSA_ASSERT(this, IsStrongHeapObject(feedback_element));
TNode<HeapObject> feedback = ToStrongHeapObject(feedback_element);
TNode<HeapObject> feedback = CAST(feedback_element);
LoadICParameters p(context, receiver, name, slot, vector);
LoadIC_Noninlined(&p, receiver_map, feedback, &var_handler, &if_handler,

View File

@ -703,8 +703,8 @@ void InterpreterAssembler::CallEpilogue() {
void InterpreterAssembler::IncrementCallCount(Node* feedback_vector,
Node* slot_id) {
Comment("increment call count");
TNode<Smi> call_count = CAST(
ToObject(LoadFeedbackVectorSlot(feedback_vector, slot_id, kPointerSize)));
TNode<Smi> call_count =
CAST(LoadFeedbackVectorSlot(feedback_vector, slot_id, kPointerSize));
// The lowest {FeedbackNexus::CallCountField::kShift} bits of the call
// count are used as flags. To increment the call count by 1 we hence
// have to increment by 1 << {FeedbackNexus::CallCountField::kShift}.
@ -957,8 +957,7 @@ Node* InterpreterAssembler::Construct(Node* target, Node* context,
{
// Check if it is an AllocationSite.
Comment("check if allocation site");
CSA_ASSERT(this, IsStrongHeapObject(feedback));
TNode<HeapObject> strong_feedback = ToStrongHeapObject(feedback);
TNode<HeapObject> strong_feedback = CAST(feedback);
GotoIfNot(IsAllocationSiteMap(LoadMap(strong_feedback)),
&check_initialized);

View File

@ -2442,8 +2442,8 @@ IGNITION_HANDLER(CreateEmptyObjectLiteral, InterpreterAssembler) {
IGNITION_HANDLER(GetTemplateObject, InterpreterAssembler) {
Node* feedback_vector = LoadFeedbackVector();
Node* slot = BytecodeOperandIdx(1);
TNode<Object> cached_value = ToObject(
LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
TNode<Object> cached_value =
CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
Label call_runtime(this, Label::kDeferred);
GotoIf(WordEqual(cached_value, SmiConstant(0)), &call_runtime);
@ -2474,7 +2474,7 @@ IGNITION_HANDLER(CreateClosure, InterpreterAssembler) {
Node* slot = BytecodeOperandIdx(1);
Node* feedback_vector = LoadFeedbackVector();
TNode<Object> feedback_cell =
ToObject(LoadFeedbackVectorSlot(feedback_vector, slot));
CAST(LoadFeedbackVectorSlot(feedback_vector, slot));
Label if_fast(this), if_slow(this, Label::kDeferred);
Branch(IsSetWord32<CreateClosureFlags::FastNewClosureBit>(flags), &if_fast,