Commit 4d7fcea2 authored by Frank Emrich's avatar Frank Emrich Committed by Commit Bot

[dict-proto] Add support for ordered property dicts, pt.5

This CL adds partial support for objects whose slow mode dictionaries
are OrderedNameDictionaries. This is the case for all slow mode objects
if V8_DICT_MODE_PROTOTYPES is enabled.

Specifically, this CL contains bailouts to the runtime in places where
the subsequent CSA or Torque code may have to access property
dictionaries.
These bailouts only happen if V8_DICT_MODE_PROTOTYPES is set, in which
case the property dictionaries are of type OrderedNameDictionary, which
cannot be handled by most CSA/Torque code.

The idea is that these bailouts are temporary and will all be removed
once we've implemented the actuall dictionary accesses in CSA/Torque.

Bug: v8:7569, v8:11167
Change-Id: I8308b2f8ba2d4dbf7918da42f995ae270c825fff
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2545711
Commit-Queue: Frank Emrich <emrich@google.com>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71311}
parent 9024b413
......@@ -468,6 +468,11 @@ TNode<HeapObject> ConstructorBuiltinsAssembler::CreateShallowObjectLiteral(
&if_dictionary, &if_fast);
BIND(&if_dictionary);
{
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
GotoIf(Int32TrueConstant(), call_runtime);
}
Comment("Copy dictionary properties");
var_properties = CopyNameDictionary(CAST(LoadSlowProperties(boilerplate)),
call_runtime);
......
......@@ -486,6 +486,11 @@ TF_BUILTIN(DeleteProperty, DeletePropertyBaseAssembler) {
Label if_index(this, &var_index), if_unique_name(this), if_notunique(this),
if_notfound(this), slow(this), if_proxy(this);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
GotoIf(Int32TrueConstant(), &slow);
}
GotoIf(TaggedIsSmi(receiver), &slow);
TNode<Map> receiver_map = LoadMap(CAST(receiver));
TNode<Uint16T> instance_type = LoadMapInstanceType(receiver_map);
......@@ -916,6 +921,11 @@ TF_BUILTIN(GetProperty, CodeStubAssembler) {
Label if_notfound(this), if_proxy(this, Label::kDeferred),
if_slow(this, Label::kDeferred);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
GotoIf(Int32TrueConstant(), &if_slow);
}
CodeStubAssembler::LookupPropertyInHolder lookup_property_in_holder =
[=](TNode<HeapObject> receiver, TNode<HeapObject> holder,
TNode<Map> holder_map, TNode<Int32T> holder_instance_type,
......@@ -971,6 +981,11 @@ TF_BUILTIN(GetPropertyWithReceiver, CodeStubAssembler) {
Label if_notfound(this), if_proxy(this, Label::kDeferred),
if_slow(this, Label::kDeferred);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
GotoIf(Int32TrueConstant(), &if_slow);
}
CodeStubAssembler::LookupPropertyInHolder lookup_property_in_holder =
[=](TNode<HeapObject> receiver, TNode<HeapObject> holder,
TNode<Map> holder_map, TNode<Int32T> holder_instance_type,
......
......@@ -28,10 +28,13 @@ class ObjectBuiltinsAssembler : public CodeStubAssembler {
protected:
void ReturnToStringFormat(TNode<Context> context, TNode<String> string);
void AddToDictionaryIf(TNode<BoolT> condition,
TNode<NameDictionary> name_dictionary,
Handle<Name> name, TNode<Object> value,
Label* bailout);
// TODO(v8:11167) remove |context| and |object| once OrderedNameDictionary
// supported.
void AddToDictionaryIf(TNode<BoolT> condition, TNode<Context> context,
TNode<Object> object,
TNode<HeapObject> name_dictionary, Handle<Name> name,
TNode<Object> value, Label* bailout);
TNode<JSObject> FromPropertyDescriptor(TNode<Context> context,
TNode<PropertyDescriptorObject> desc);
TNode<JSObject> FromPropertyDetails(TNode<Context> context,
......@@ -1030,6 +1033,12 @@ TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) {
Label call_runtime(this, Label::kDeferred), prototype_valid(this),
no_properties(this);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
GotoIf(Int32TrueConstant(), &call_runtime);
}
{
Comment("Argument 1 check: prototype");
GotoIf(IsNull(prototype), &prototype_valid);
......@@ -1266,6 +1275,12 @@ TF_BUILTIN(ObjectGetOwnPropertyDescriptor, ObjectBuiltinsAssembler) {
Label if_keyisindex(this), if_iskeyunique(this),
call_runtime(this, Label::kDeferred),
return_undefined(this, Label::kDeferred), if_notunique_name(this);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
GotoIf(Int32TrueConstant(), &call_runtime);
}
TNode<Map> map = LoadMap(object);
TNode<Uint16T> instance_type = LoadMapInstanceType(map);
GotoIf(IsSpecialReceiverInstanceType(instance_type), &call_runtime);
......@@ -1339,13 +1354,23 @@ TF_BUILTIN(ObjectGetOwnPropertyDescriptor, ObjectBuiltinsAssembler) {
args.PopAndReturn(UndefinedConstant());
}
// TODO(v8:11167) remove remove |context| and |object| parameters once
// OrderedNameDictionary supported.
void ObjectBuiltinsAssembler::AddToDictionaryIf(
TNode<BoolT> condition, TNode<NameDictionary> name_dictionary,
Handle<Name> name, TNode<Object> value, Label* bailout) {
TNode<BoolT> condition, TNode<Context> context, TNode<Object> object,
TNode<HeapObject> name_dictionary, Handle<Name> name, TNode<Object> value,
Label* bailout) {
Label done(this);
GotoIfNot(condition, &done);
Add<NameDictionary>(name_dictionary, HeapConstant(name), value, bailout);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
CallRuntime(Runtime::kAddDictionaryProperty, context, object,
HeapConstant(name), value);
} else {
Add<NameDictionary>(CAST(name_dictionary), HeapConstant(name), value,
bailout);
}
Goto(&done);
BIND(&done);
......@@ -1401,7 +1426,10 @@ TNode<JSObject> ObjectBuiltinsAssembler::FromPropertyDescriptor(
native_context, Context::SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP));
// We want to preallocate the slots for value, writable, get, set,
// enumerable and configurable - a total of 6
TNode<NameDictionary> properties = AllocateNameDictionary(6);
TNode<HeapObject> properties =
V8_DICT_MODE_PROTOTYPES_BOOL
? TNode<HeapObject>(AllocateOrderedNameDictionary(6))
: AllocateNameDictionary(6);
TNode<JSObject> js_desc = AllocateJSObjectFromMap(map, properties);
Label bailout(this, Label::kDeferred);
......@@ -1409,33 +1437,33 @@ TNode<JSObject> ObjectBuiltinsAssembler::FromPropertyDescriptor(
Factory* factory = isolate()->factory();
TNode<Object> value =
LoadObjectField(desc, PropertyDescriptorObject::kValueOffset);
AddToDictionaryIf(IsNotTheHole(value), properties, factory->value_string(),
value, &bailout);
AddToDictionaryIf(IsNotTheHole(value), context, js_desc, properties,
factory->value_string(), value, &bailout);
AddToDictionaryIf(
IsSetWord32<PropertyDescriptorObject::HasWritableBit>(flags),
properties, factory->writable_string(),
IsSetWord32<PropertyDescriptorObject::HasWritableBit>(flags), context,
js_desc, properties, factory->writable_string(),
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsWritableBit>(flags)),
&bailout);
TNode<Object> get =
LoadObjectField(desc, PropertyDescriptorObject::kGetOffset);
AddToDictionaryIf(IsNotTheHole(get), properties, factory->get_string(), get,
&bailout);
AddToDictionaryIf(IsNotTheHole(get), context, js_desc, properties,
factory->get_string(), get, &bailout);
TNode<Object> set =
LoadObjectField(desc, PropertyDescriptorObject::kSetOffset);
AddToDictionaryIf(IsNotTheHole(set), properties, factory->set_string(), set,
&bailout);
AddToDictionaryIf(IsNotTheHole(set), context, js_desc, properties,
factory->set_string(), set, &bailout);
AddToDictionaryIf(
IsSetWord32<PropertyDescriptorObject::HasEnumerableBit>(flags),
properties, factory->enumerable_string(),
IsSetWord32<PropertyDescriptorObject::HasEnumerableBit>(flags), context,
js_desc, properties, factory->enumerable_string(),
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags)),
&bailout);
AddToDictionaryIf(
IsSetWord32<PropertyDescriptorObject::HasConfigurableBit>(flags),
properties, factory->configurable_string(),
context, js_desc, properties, factory->configurable_string(),
SelectBooleanConstant(
IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)),
&bailout);
......@@ -1443,9 +1471,12 @@ TNode<JSObject> ObjectBuiltinsAssembler::FromPropertyDescriptor(
js_descriptor = js_desc;
Goto(&return_desc);
BIND(&bailout);
CSA_ASSERT(this, Int32Constant(0));
Unreachable();
if (!V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) make unconditional once OrderedNameDictionary supported.
BIND(&bailout);
CSA_ASSERT(this, Int32Constant(0));
Unreachable();
}
}
BIND(&return_desc);
......
......@@ -332,18 +332,28 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(
// - Receiver is extensible
// - Receiver has no interceptors
Label add_dictionary_property_slow(this, Label::kDeferred);
Add<NameDictionary>(CAST(properties), name, capture,
&add_dictionary_property_slow);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
CallRuntime(Runtime::kAddDictionaryProperty, context, group_object,
name, capture);
} else {
Add<NameDictionary>(CAST(properties), name, capture,
&add_dictionary_property_slow);
}
var_i = i_plus_2;
Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), &out,
&loop);
BIND(&add_dictionary_property_slow);
// If the dictionary needs resizing, the above Add call will jump here
// before making any changes. This shouldn't happen because we allocated
// the dictionary with enough space above.
Unreachable();
if (!V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) make unconditional once OrderedNameDictionary
// supported.
BIND(&add_dictionary_property_slow);
// If the dictionary needs resizing, the above Add call will jump here
// before making any changes. This shouldn't happen because we allocated
// the dictionary with enough space above.
Unreachable();
}
}
}
......
......@@ -8371,9 +8371,10 @@ void CodeStubAssembler::ForEachEnumerableOwnProperty(
// guaranteed that the object has a simple shape, and that the key
// is a name.
var_map = LoadMap(object);
TryLookupPropertyInSimpleObject(
object, var_map.value(), next_key, &if_found_fast,
&if_found_dict, &var_meta_storage, &var_entry, &next_iteration);
TryLookupPropertyInSimpleObject(object, var_map.value(), next_key,
&if_found_fast, &if_found_dict,
&var_meta_storage, &var_entry,
&next_iteration, bailout);
}
BIND(&if_found_fast);
......@@ -8394,6 +8395,12 @@ void CodeStubAssembler::ForEachEnumerableOwnProperty(
}
BIND(&if_found_dict);
{
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167, v8:11177) Only here due to SetDataProperties
// workaround.
GotoIf(Int32TrueConstant(), bailout);
}
TNode<NameDictionary> dictionary = CAST(var_meta_storage.value());
TNode<IntPtrT> entry = var_entry.value();
......@@ -8575,7 +8582,7 @@ void CodeStubAssembler::TryLookupPropertyInSimpleObject(
TNode<JSObject> object, TNode<Map> map, TNode<Name> unique_name,
Label* if_found_fast, Label* if_found_dict,
TVariable<HeapObject>* var_meta_storage, TVariable<IntPtrT>* var_name_index,
Label* if_not_found) {
Label* if_not_found, Label* bailout) {
CSA_ASSERT(this, IsSimpleObjectMap(map));
CSA_ASSERT(this, IsUniqueNameNoCachedIndex(unique_name));
......@@ -8593,6 +8600,11 @@ void CodeStubAssembler::TryLookupPropertyInSimpleObject(
}
BIND(&if_isslowmap);
{
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167, v8:11177) Only here due to SetDataProperties workaround.
GotoIf(Int32TrueConstant(), bailout);
}
TNode<NameDictionary> dictionary = CAST(LoadSlowProperties(object));
*var_meta_storage = dictionary;
......@@ -8612,7 +8624,7 @@ void CodeStubAssembler::TryLookupProperty(
TryLookupPropertyInSimpleObject(CAST(object), map, unique_name, if_found_fast,
if_found_dict, var_meta_storage,
var_name_index, if_not_found);
var_name_index, if_not_found, if_bailout);
BIND(&if_objectisspecial);
{
......@@ -12246,6 +12258,11 @@ TNode<Oddball> CodeStubAssembler::HasProperty(TNode<Context> context,
Label call_runtime(this, Label::kDeferred), return_true(this),
return_false(this), end(this), if_proxy(this, Label::kDeferred);
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
GotoIf(Int32TrueConstant(), &call_runtime);
}
CodeStubAssembler::LookupPropertyInHolder lookup_property_in_holder =
[this, &return_true](
TNode<HeapObject> receiver, TNode<HeapObject> holder,
......
......@@ -3041,13 +3041,15 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// This is a building block for TryLookupProperty() above. Supports only
// non-special fast and dictionary objects.
// TODO(v8:11167, v8:11177) |bailout| only needed for SetDataProperties
// workaround.
void TryLookupPropertyInSimpleObject(TNode<JSObject> object, TNode<Map> map,
TNode<Name> unique_name,
Label* if_found_fast,
Label* if_found_dict,
TVariable<HeapObject>* var_meta_storage,
TVariable<IntPtrT>* var_name_index,
Label* if_not_found);
Label* if_not_found, Label* bailout);
// This method jumps to if_found if the element is known to exist. To
// if_absent if it's known to not exist. To if_not_found if the prototype
......
......@@ -868,6 +868,11 @@ TNode<Object> AccessorAssembler::HandleProtoHandler(
BIND(&if_lookup_on_lookup_start_object);
{
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
GotoIf(Int32TrueConstant(), miss);
}
// Dictionary lookup on lookup start object is not necessary for
// Load/StoreGlobalIC (which is the only case when the
// lookup_start_object can be a JSGlobalObject) because prototype
......@@ -2444,6 +2449,11 @@ void AccessorAssembler::GenericPropertyLoad(
BIND(&if_property_dictionary);
{
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
GotoIf(Int32TrueConstant(), slow);
}
Comment("dictionary property load");
// We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out
// seeing global objects here (which would need special handling).
......
......@@ -29,6 +29,8 @@ LoadHandler::Kind LoadHandler::GetHandlerKind(Smi smi_handler) {
}
Handle<Smi> LoadHandler::LoadNormal(Isolate* isolate) {
// TODO(v8:11167) remove DCHECK once OrderedNameDictionary supported.
DCHECK(!V8_DICT_MODE_PROTOTYPES_BOOL);
int config = KindBits::encode(kNormal);
return handle(Smi::FromInt(config), isolate);
}
......@@ -128,6 +130,8 @@ Handle<Smi> StoreHandler::StoreGlobalProxy(Isolate* isolate) {
}
Handle<Smi> StoreHandler::StoreNormal(Isolate* isolate) {
// TODO(v8:11167) remove DCHECK once OrderedNameDictionary supported.
DCHECK(!V8_DICT_MODE_PROTOTYPES_BOOL);
int config = KindBits::encode(kNormal);
return handle(Smi::FromInt(config), isolate);
}
......
......@@ -116,6 +116,9 @@ Handle<Object> LoadHandler::LoadFromPrototype(
Isolate* isolate, Handle<Map> lookup_start_object_map,
Handle<JSReceiver> holder, Handle<Smi> smi_handler,
MaybeObjectHandle maybe_data1, MaybeObjectHandle maybe_data2) {
// TODO(v8:11167) remove DCHECK once OrderedNameDictionary supported.
DCHECK_IMPLIES(V8_DICT_MODE_PROTOTYPES_BOOL,
GetHandlerKind(*smi_handler) != Kind::kNormal);
MaybeObjectHandle data1;
if (maybe_data1.is_null()) {
data1 = MaybeObjectHandle::Weak(holder);
......@@ -271,6 +274,10 @@ Handle<Object> StoreHandler::StoreThroughPrototype(
Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
Handle<Smi> smi_handler, MaybeObjectHandle maybe_data1,
MaybeObjectHandle maybe_data2) {
// TODO(v8:11167) remove DCHECK once OrderedNameDictionary supported.
DCHECK_IMPLIES(V8_DICT_MODE_PROTOTYPES_BOOL,
KindBits::decode(smi_handler->value()) != Kind::kNormal);
MaybeObjectHandle data1;
if (maybe_data1.is_null()) {
data1 = MaybeObjectHandle::Weak(holder);
......
......@@ -12,6 +12,7 @@
#include "src/builtins/accessors.h"
#include "src/codegen/code-factory.h"
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
#include "src/execution/arguments-inl.h"
#include "src/execution/execution.h"
#include "src/execution/frames-inl.h"
......@@ -922,8 +923,12 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
isolate(), map, holder, smi_handler,
MaybeObjectHandle::Weak(lookup->GetPropertyCell()));
} else {
smi_handler = LoadHandler::LoadNormal(isolate());
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
smi_handler = LoadHandler::LoadSlow(isolate());
} else {
smi_handler = LoadHandler::LoadNormal(isolate());
}
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
if (holder_is_lookup_start_object) return smi_handler;
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
......@@ -966,8 +971,12 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
isolate(), map, holder, smi_handler,
MaybeObjectHandle::Weak(lookup->GetPropertyCell()));
}
smi_handler = LoadHandler::LoadNormal(isolate());
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167) remove once OrderedNameDictionary supported.
smi_handler = LoadHandler::LoadSlow(isolate());
} else {
smi_handler = LoadHandler::LoadNormal(isolate());
}
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
if (holder_is_lookup_start_object) return smi_handler;
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
......@@ -1794,7 +1803,12 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
}
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
DCHECK(holder.is_identical_to(receiver));
return MaybeObjectHandle(StoreHandler::StoreNormal(isolate()));
// TODO(v8:11167) don't create slow hanlder once OrderedNameDictionary
// supported.
Handle<Smi> handler = V8_DICT_MODE_PROTOTYPES_BOOL
? StoreHandler::StoreSlow(isolate())
: StoreHandler::StoreNormal(isolate());
return MaybeObjectHandle(handler);
}
// -------------- Elements (for TypedArrays) -------------
......
......@@ -827,6 +827,10 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
BIND(&dictionary_properties);
{
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
// TODO(v8:11167, v8:11177) Only here due to SetDataProperties workaround.
GotoIf(Int32TrueConstant(), slow);
}
Comment("dictionary property store");
// We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out
// seeing global objects here (which would need special handling).
......
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