Commit 541a0b75 authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

[turbofan] Use heap broker for accesses in JSCreateLowering::ReduceJSCreateLiteralArrayOrObject.

This does not move the dependency management there, yet.

Bug: v8:7790
Change-Id: Ia8b473a89c2853ffeba4adf84ac8814f403279c9
Reviewed-on: https://chromium-review.googlesource.com/1112256
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54004}
parent 75f14dbf
......@@ -56,81 +56,6 @@ const int kElementLoopUnrollLimit = 16;
const int kFunctionContextAllocationLimit = 16;
const int kBlockContextAllocationLimit = 16;
// Determines whether the given array or object literal boilerplate satisfies
// all limits to be considered for fast deep-copying and computes the total
// size of all objects that are part of the graph.
bool IsFastLiteral(Handle<JSObject> boilerplate, int max_depth,
int* max_properties) {
DCHECK_GE(max_depth, 0);
DCHECK_GE(*max_properties, 0);
// Make sure the boilerplate map is not deprecated.
if (!JSObject::TryMigrateInstance(boilerplate)) return false;
// Check for too deep nesting.
if (max_depth == 0) return false;
// Check the elements.
Isolate* const isolate = boilerplate->GetIsolate();
Handle<FixedArrayBase> elements(boilerplate->elements(), isolate);
if (elements->length() > 0 &&
elements->map() != isolate->heap()->fixed_cow_array_map()) {
if (boilerplate->HasSmiOrObjectElements()) {
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
int length = elements->length();
for (int i = 0; i < length; i++) {
if ((*max_properties)-- == 0) return false;
Handle<Object> value(fast_elements->get(i), isolate);
if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
if (!IsFastLiteral(value_object, max_depth - 1, max_properties)) {
return false;
}
}
}
} else if (boilerplate->HasDoubleElements()) {
if (elements->Size() > kMaxRegularHeapObjectSize) return false;
} else {
return false;
}
}
// TODO(turbofan): Do we want to support out-of-object properties?
if (!(boilerplate->HasFastProperties() &&
boilerplate->property_array()->length() == 0)) {
return false;
}
// Check the in-object properties.
Handle<DescriptorArray> descriptors(
boilerplate->map()->instance_descriptors(), isolate);
int limit = boilerplate->map()->NumberOfOwnDescriptors();
for (int i = 0; i < limit; i++) {
PropertyDetails details = descriptors->GetDetails(i);
if (details.location() != kField) continue;
DCHECK_EQ(kData, details.kind());
if ((*max_properties)-- == 0) return false;
FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate);
if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
if (!IsFastLiteral(value_object, max_depth - 1, max_properties)) {
return false;
}
}
}
return true;
}
// Maximum depth and total number of elements and properties for literal
// graphs to be considered for fast deep-copying. The limit is chosen to
// match the maximum number of inobject properties, to ensure that the
// performance of using object literals is not worse than using constructor
// functions, see crbug.com/v8/6211 for details.
const int kMaxFastLiteralDepth = 3;
const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties;
} // namespace
Reduction JSCreateLowering::Reduce(Node* node) {
......@@ -1220,20 +1145,20 @@ Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Handle<Object> feedback(
p.feedback().vector()->Get(p.feedback().slot())->ToObject(), isolate());
if (feedback->IsAllocationSite()) {
Handle<AllocationSite> site = Handle<AllocationSite>::cast(feedback);
Handle<JSObject> boilerplate(site->boilerplate(), isolate());
int max_properties = kMaxFastLiteralProperties;
if (IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
FeedbackVectorRef feedback_vector(p.feedback().vector());
ObjectRef feedback =
feedback_vector.get(js_heap_broker(), p.feedback().slot());
if (feedback.IsAllocationSite()) {
AllocationSiteRef site = feedback.AsAllocationSite();
if (site.IsFastLiteral(js_heap_broker())) {
PretenureFlag pretenure = NOT_TENURED;
if (FLAG_allocation_site_pretenuring) {
pretenure = site->GetPretenureMode();
dependencies()->AssumeTenuringDecision(site);
pretenure = site.GetPretenureMode();
dependencies()->AssumeTenuringDecision(site.object<AllocationSite>());
}
AssumeAllocationSiteTransitionDeepDependencies(dependencies(), isolate(),
site);
JSObjectRef boilerplate = site.boilerplate(js_heap_broker());
AssumeAllocationSiteTransitionDeepDependencies(
dependencies(), isolate(), site.object<AllocationSite>());
Node* value = effect =
AllocateFastLiteral(effect, control, boilerplate, pretenure);
ReplaceWithValue(node, value, effect, control);
......@@ -1720,43 +1645,41 @@ Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
}
Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
Handle<JSObject> boilerplate,
JSObjectRef boilerplate,
PretenureFlag pretenure) {
// Setup the properties backing store.
Node* properties = jsgraph()->EmptyFixedArrayConstant();
// Compute the in-object properties to store first (might have effects).
Handle<Map> boilerplate_map(boilerplate->map(), isolate());
MapRef boilerplate_map = boilerplate.map(js_heap_broker());
ZoneVector<std::pair<FieldAccess, Node*>> inobject_fields(zone());
inobject_fields.reserve(boilerplate_map->GetInObjectProperties());
int const boilerplate_nof = boilerplate_map->NumberOfOwnDescriptors();
inobject_fields.reserve(boilerplate_map.GetInObjectProperties());
int const boilerplate_nof = boilerplate_map.NumberOfOwnDescriptors();
for (int i = 0; i < boilerplate_nof; ++i) {
PropertyDetails const property_details =
boilerplate_map->instance_descriptors()->GetDetails(i);
boilerplate_map.GetPropertyDetails(i);
if (property_details.location() != kField) continue;
DCHECK_EQ(kData, property_details.kind());
Handle<Name> property_name(
boilerplate_map->instance_descriptors()->GetKey(i), isolate());
FieldIndex index = FieldIndex::ForDescriptor(*boilerplate_map, i);
FieldAccess access = {kTaggedBase, index.offset(),
property_name, MaybeHandle<Map>(),
Type::Any(), MachineType::AnyTagged(),
NameRef property_name = boilerplate_map.GetPropertyKey(js_heap_broker(), i);
FieldIndex index = boilerplate_map.GetFieldIndexFor(i);
FieldAccess access = {
kTaggedBase, index.offset(), property_name.object<Name>(),
MaybeHandle<Map>(), Type::Any(), MachineType::AnyTagged(),
kFullWriteBarrier};
Node* value;
if (boilerplate->IsUnboxedDoubleField(index)) {
if (boilerplate.IsUnboxedDoubleField(index)) {
access.machine_type = MachineType::Float64();
access.type = Type::Number();
value = jsgraph()->Constant(boilerplate->RawFastDoublePropertyAt(index));
value = jsgraph()->Constant(boilerplate.RawFastDoublePropertyAt(index));
} else {
Handle<Object> boilerplate_value(boilerplate->RawFastPropertyAt(index),
isolate());
if (boilerplate_value->IsJSObject()) {
Handle<JSObject> boilerplate_object =
Handle<JSObject>::cast(boilerplate_value);
ObjectRef boilerplate_value =
boilerplate.RawFastPropertyAt(js_heap_broker(), index);
if (boilerplate_value.IsJSObject()) {
JSObjectRef boilerplate_object = boilerplate_value.AsJSObject();
value = effect =
AllocateFastLiteral(effect, control, boilerplate_object, pretenure);
} else if (property_details.representation().IsDouble()) {
double number = Handle<HeapNumber>::cast(boilerplate_value)->value();
double number = boilerplate_value.AsMutableHeapNumber().value();
// Allocate a mutable HeapNumber box and store the value into it.
AllocationBuilder builder(jsgraph(), effect, control);
builder.Allocate(HeapNumber::kSize, pretenure);
......@@ -1767,22 +1690,23 @@ Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
value = effect = builder.Finish();
} else if (property_details.representation().IsSmi()) {
// Ensure that value is stored as smi.
value = boilerplate_value->IsUninitialized(isolate())
value = boilerplate_value.oddball_type(js_heap_broker()) ==
OddballType::kUninitialized
? jsgraph()->ZeroConstant()
: jsgraph()->Constant(boilerplate_value);
: jsgraph()->Constant(boilerplate_value.AsSmi());
} else {
value = jsgraph()->Constant(boilerplate_value);
value = jsgraph()->Constant(js_heap_broker(), boilerplate_value);
}
}
inobject_fields.push_back(std::make_pair(access, value));
}
// Fill slack at the end of the boilerplate object with filler maps.
int const boilerplate_length = boilerplate_map->GetInObjectProperties();
int const boilerplate_length = boilerplate_map.GetInObjectProperties();
for (int index = static_cast<int>(inobject_fields.size());
index < boilerplate_length; ++index) {
FieldAccess access =
AccessBuilder::ForJSObjectInObjectProperty(boilerplate_map, index);
FieldAccess access = AccessBuilder::ForJSObjectInObjectProperty(
boilerplate_map.object<Map>(), index);
Node* value = jsgraph()->HeapConstant(factory()->one_pointer_filler_map());
inobject_fields.push_back(std::make_pair(access, value));
}
......@@ -1794,16 +1718,16 @@ Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
// Actually allocate and initialize the object.
AllocationBuilder builder(jsgraph(), effect, control);
builder.Allocate(boilerplate_map->instance_size(), pretenure,
Type::For(js_heap_broker(), boilerplate_map));
builder.Store(AccessBuilder::ForMap(), boilerplate_map);
builder.Allocate(boilerplate_map.instance_size(), pretenure,
Type::For(js_heap_broker(), boilerplate_map.object<Map>()));
builder.Store(AccessBuilder::ForMap(), boilerplate_map.object<Map>());
builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
builder.Store(AccessBuilder::ForJSObjectElements(), elements);
if (boilerplate_map->IsJSArrayMap()) {
Handle<JSArray> boilerplate_array = Handle<JSArray>::cast(boilerplate);
if (boilerplate_map.IsJSArrayMap()) {
JSArrayRef boilerplate_array = boilerplate.AsJSArray();
builder.Store(
AccessBuilder::ForJSArrayLength(boilerplate_array->GetElementsKind()),
handle(boilerplate_array->length(), isolate()));
AccessBuilder::ForJSArrayLength(boilerplate_array.GetElementsKind()),
boilerplate_array.length(js_heap_broker()).object<Object>());
}
for (auto const& inobject_field : inobject_fields) {
builder.Store(inobject_field.first, inobject_field.second);
......@@ -1811,57 +1735,48 @@ Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
return builder.Finish();
}
Node* JSCreateLowering::AllocateFastLiteralElements(
Node* effect, Node* control, Handle<JSObject> boilerplate,
Node* JSCreateLowering::AllocateFastLiteralElements(Node* effect, Node* control,
JSObjectRef boilerplate,
PretenureFlag pretenure) {
Handle<FixedArrayBase> boilerplate_elements(boilerplate->elements(),
isolate());
FixedArrayBaseRef boilerplate_elements =
boilerplate.elements(js_heap_broker());
// Empty or copy-on-write elements just store a constant.
if (boilerplate_elements->length() == 0 ||
boilerplate_elements->map() == isolate()->heap()->fixed_cow_array_map()) {
if (pretenure == TENURED &&
isolate()->heap()->InNewSpace(*boilerplate_elements)) {
// If we would like to pretenure a fixed cow array, we must ensure that
// the array is already in old space, otherwise we'll create too many
// old-to-new-space pointers (overflowing the store buffer).
boilerplate_elements = Handle<FixedArrayBase>(
isolate()->factory()->CopyAndTenureFixedCOWArray(
Handle<FixedArray>::cast(boilerplate_elements)));
boilerplate->set_elements(*boilerplate_elements);
int const elements_length = boilerplate_elements.length();
MapRef elements_map = boilerplate_elements.map(js_heap_broker());
if (boilerplate_elements.length() == 0 ||
elements_map.IsFixedCowArrayMap(js_heap_broker())) {
if (pretenure == TENURED) {
boilerplate.EnsureElementsTenured(js_heap_broker());
boilerplate_elements = boilerplate.elements(js_heap_broker());
}
return jsgraph()->HeapConstant(boilerplate_elements);
return jsgraph()->HeapConstant(boilerplate_elements.object<HeapObject>());
}
// Compute the elements to store first (might have effects).
int const elements_length = boilerplate_elements->length();
Handle<Map> elements_map(boilerplate_elements->map(), isolate());
ZoneVector<Node*> elements_values(elements_length, zone());
if (elements_map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE) {
Handle<FixedDoubleArray> elements =
Handle<FixedDoubleArray>::cast(boilerplate_elements);
if (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE) {
FixedDoubleArrayRef elements = boilerplate_elements.AsFixedDoubleArray();
for (int i = 0; i < elements_length; ++i) {
if (elements->is_the_hole(i)) {
if (elements.is_the_hole(i)) {
elements_values[i] = jsgraph()->TheHoleConstant();
} else {
elements_values[i] = jsgraph()->Constant(elements->get_scalar(i));
elements_values[i] = jsgraph()->Constant(elements.get_scalar(i));
}
}
} else {
Handle<FixedArray> elements =
Handle<FixedArray>::cast(boilerplate_elements);
FixedArrayRef elements = boilerplate_elements.AsFixedArray();
for (int i = 0; i < elements_length; ++i) {
if (elements->is_the_hole(isolate(), i)) {
if (elements.is_the_hole(js_heap_broker(), i)) {
elements_values[i] = jsgraph()->TheHoleConstant();
} else {
Handle<Object> element_value(elements->get(i), isolate());
if (element_value->IsJSObject()) {
Handle<JSObject> boilerplate_object =
Handle<JSObject>::cast(element_value);
ObjectRef element_value = elements.get(js_heap_broker(), i);
if (element_value.IsJSObject()) {
elements_values[i] = effect = AllocateFastLiteral(
effect, control, boilerplate_object, pretenure);
effect, control, element_value.AsJSObject(), pretenure);
} else {
elements_values[i] = jsgraph()->Constant(element_value);
elements_values[i] =
jsgraph()->Constant(js_heap_broker(), element_value);
}
}
}
......@@ -1869,9 +1784,9 @@ Node* JSCreateLowering::AllocateFastLiteralElements(
// Allocate the backing store array and store the elements.
AllocationBuilder builder(jsgraph(), effect, control);
builder.AllocateArray(elements_length, elements_map, pretenure);
builder.AllocateArray(elements_length, elements_map.object<Map>(), pretenure);
ElementAccess const access =
(elements_map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE)
(elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE)
? AccessBuilder::ForFixedDoubleArrayElement()
: AccessBuilder::ForFixedArrayElement();
for (int i = 0; i < elements_length; ++i) {
......
......@@ -24,6 +24,7 @@ namespace compiler {
class CommonOperatorBuilder;
class JSGraph;
class JSHeapBroker;
class JSObjectRef;
class JSOperatorBuilder;
class MachineOperatorBuilder;
class SimplifiedOperatorBuilder;
......@@ -97,10 +98,9 @@ class V8_EXPORT_PRIVATE JSCreateLowering final
std::vector<Node*> const& values,
PretenureFlag pretenure);
Node* AllocateFastLiteral(Node* effect, Node* control,
Handle<JSObject> boilerplate,
PretenureFlag pretenure);
JSObjectRef boilerplate, PretenureFlag pretenure);
Node* AllocateFastLiteralElements(Node* effect, Node* control,
Handle<JSObject> boilerplate,
JSObjectRef boilerplate,
PretenureFlag pretenure);
Node* AllocateLiteralRegExp(Node* effect, Node* control,
Handle<JSRegExp> boilerplate);
......
......@@ -11,27 +11,48 @@ namespace compiler {
HeapObjectRef::HeapObjectRef(Handle<Object> object) : ObjectRef(object) {
AllowHandleDereference handle_dereference;
SLOW_DCHECK(object->IsHeapObject());
DCHECK(object->IsHeapObject());
}
JSFunctionRef::JSFunctionRef(Handle<Object> object) : HeapObjectRef(object) {
MapRef HeapObjectRef::map(const JSHeapBroker* broker) const {
AllowHandleDereference allow_handle_dereference;
return MapRef(handle(object<HeapObject>()->map(), broker->isolate()));
}
JSFunctionRef::JSFunctionRef(Handle<Object> object) : JSObjectRef(object) {
AllowHandleDereference handle_dereference;
SLOW_DCHECK(object->IsJSFunction());
DCHECK(object->IsJSFunction());
}
HeapNumberRef::HeapNumberRef(Handle<Object> object) : HeapObjectRef(object) {
AllowHandleDereference handle_dereference;
SLOW_DCHECK(object->IsHeapNumber());
DCHECK(object->IsHeapNumber());
}
MutableHeapNumberRef::MutableHeapNumberRef(Handle<Object> object)
: HeapObjectRef(object) {
AllowHandleDereference handle_dereference;
DCHECK(object->IsMutableHeapNumber());
}
double HeapNumberRef::value() const {
AllowHandleDereference allow_handle_dereference;
return object<HeapNumber>()->value();
}
double MutableHeapNumberRef::value() const {
AllowHandleDereference allow_handle_dereference;
return object<HeapNumber>()->value();
}
ContextRef::ContextRef(Handle<Object> object) : HeapObjectRef(object) {
AllowHandleDereference handle_dereference;
SLOW_DCHECK(object->IsContext());
DCHECK(object->IsContext());
}
NativeContextRef::NativeContextRef(Handle<Object> object) : ContextRef(object) {
AllowHandleDereference handle_dereference;
SLOW_DCHECK(object->IsNativeContext());
DCHECK(object->IsNativeContext());
}
bool ObjectRef::IsSmi() const {
......@@ -72,10 +93,11 @@ HeapObjectType JSHeapBroker::HeapObjectTypeFromMap(Map* map) const {
oddball_type = OddballType::kBoolean;
} else if (map == heap->the_hole_map()) {
oddball_type = OddballType::kHole;
} else if (map == heap->uninitialized_map()) {
oddball_type = OddballType::kUninitialized;
} else {
oddball_type = OddballType::kOther;
DCHECK(map == heap->uninitialized_map() ||
map == heap->termination_exception_map() ||
DCHECK(map == heap->termination_exception_map() ||
map == heap->arguments_marker_map() ||
map == heap->optimized_out_map() ||
map == heap->stale_register_map());
......@@ -105,7 +127,7 @@ HEAP_BROKER_KIND_LIST(HEAP_KIND_FUNCTIONS_DEF)
#define HEAP_DATA_FUNCTIONS_DEF(Name) \
Name##Ref ObjectRef::As##Name() const { \
SLOW_DCHECK(Is##Name()); \
DCHECK(Is##Name()); \
return Name##Ref(object<HeapObject>()); \
}
HEAP_BROKER_DATA_LIST(HEAP_DATA_FUNCTIONS_DEF)
......@@ -116,11 +138,6 @@ HeapObjectType HeapObjectRef::type(const JSHeapBroker* broker) const {
return broker->HeapObjectTypeFromMap(object<HeapObject>()->map());
}
double HeapNumberRef::value() const {
AllowHandleDereference allow_handle_dereference;
return object<HeapObject>()->Number();
}
bool JSFunctionRef::HasBuiltinFunctionId() const {
AllowHandleDereference allow_handle_dereference;
return object<JSFunction>()->shared()->HasBuiltinFunctionId();
......@@ -133,13 +150,13 @@ BuiltinFunctionId JSFunctionRef::GetBuiltinFunctionId() const {
NameRef::NameRef(Handle<Object> object) : HeapObjectRef(object) {
AllowHandleDereference handle_dereference;
SLOW_DCHECK(object->IsName());
DCHECK(object->IsName());
}
ScriptContextTableRef::ScriptContextTableRef(Handle<Object> object)
: HeapObjectRef(object) {
AllowHandleDereference handle_dereference;
SLOW_DCHECK(object->IsScriptContextTable());
DCHECK(object->IsScriptContextTable());
}
base::Optional<ScriptContextTableRef::LookupResult>
......@@ -172,6 +189,239 @@ OddballType ObjectRef::oddball_type(const JSHeapBroker* broker) const {
: AsHeapObject().type(broker).oddball_type();
}
ObjectRef FeedbackVectorRef::get(const JSHeapBroker* broker,
FeedbackSlot slot) const {
AllowHandleDereference handle_dereference;
Handle<Object> value(object<FeedbackVector>()->Get(slot)->ToObject(),
broker->isolate());
return ObjectRef(value);
}
JSObjectRef AllocationSiteRef::boilerplate(const JSHeapBroker* broker) const {
AllowHandleDereference handle_dereference;
Handle<JSObject> value(object<AllocationSite>()->boilerplate(),
broker->isolate());
return JSObjectRef(value);
}
bool JSObjectRef::IsUnboxedDoubleField(FieldIndex index) const {
AllowHandleDereference handle_dereference;
return object<JSObject>()->IsUnboxedDoubleField(index);
}
double JSObjectRef::RawFastDoublePropertyAt(FieldIndex index) const {
AllowHandleDereference handle_dereference;
return object<JSObject>()->RawFastDoublePropertyAt(index);
}
ObjectRef JSObjectRef::RawFastPropertyAt(const JSHeapBroker* broker,
FieldIndex index) const {
AllowHandleDereference handle_dereference;
return ObjectRef(
handle(object<JSObject>()->RawFastPropertyAt(index), broker->isolate()));
}
FixedArrayBaseRef JSObjectRef::elements(const JSHeapBroker* broker) const {
AllowHandleDereference handle_dereference;
return FixedArrayBaseRef(
handle(object<JSObject>()->elements(), broker->isolate()));
}
namespace {
// Determines whether the given array or object literal boilerplate satisfies
// all limits to be considered for fast deep-copying and computes the total
// size of all objects that are part of the graph.
bool IsFastLiteralHelper(Handle<JSObject> boilerplate, int max_depth,
int* max_properties) {
DCHECK_GE(max_depth, 0);
DCHECK_GE(*max_properties, 0);
// Make sure the boilerplate map is not deprecated.
if (!JSObject::TryMigrateInstance(boilerplate)) return false;
// Check for too deep nesting.
if (max_depth == 0) return false;
// Check the elements.
Isolate* const isolate = boilerplate->GetIsolate();
Handle<FixedArrayBase> elements(boilerplate->elements(), isolate);
if (elements->length() > 0 &&
elements->map() != isolate->heap()->fixed_cow_array_map()) {
if (boilerplate->HasSmiOrObjectElements()) {
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
int length = elements->length();
for (int i = 0; i < length; i++) {
if ((*max_properties)-- == 0) return false;
Handle<Object> value(fast_elements->get(i), isolate);
if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
if (!IsFastLiteralHelper(value_object, max_depth - 1,
max_properties)) {
return false;
}
}
}
} else if (boilerplate->HasDoubleElements()) {
if (elements->Size() > kMaxRegularHeapObjectSize) return false;
} else {
return false;
}
}
// TODO(turbofan): Do we want to support out-of-object properties?
if (!(boilerplate->HasFastProperties() &&
boilerplate->property_array()->length() == 0)) {
return false;
}
// Check the in-object properties.
Handle<DescriptorArray> descriptors(
boilerplate->map()->instance_descriptors(), isolate);
int limit = boilerplate->map()->NumberOfOwnDescriptors();
for (int i = 0; i < limit; i++) {
PropertyDetails details = descriptors->GetDetails(i);
if (details.location() != kField) continue;
DCHECK_EQ(kData, details.kind());
if ((*max_properties)-- == 0) return false;
FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate);
if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
if (!IsFastLiteralHelper(value_object, max_depth - 1, max_properties)) {
return false;
}
}
}
return true;
}
} // namespace
// Maximum depth and total number of elements and properties for literal
// graphs to be considered for fast deep-copying. The limit is chosen to
// match the maximum number of inobject properties, to ensure that the
// performance of using object literals is not worse than using constructor
// functions, see crbug.com/v8/6211 for details.
const int kMaxFastLiteralDepth = 3;
const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties;
// Determines whether the given array or object literal boilerplate satisfies
// all limits to be considered for fast deep-copying and computes the total
// size of all objects that are part of the graph.
bool AllocationSiteRef::IsFastLiteral(const JSHeapBroker* broker) {
AllowHandleDereference allow_handle_dereference;
int max_properties = kMaxFastLiteralProperties;
Handle<JSObject> boilerplate(object<AllocationSite>()->boilerplate(),
broker->isolate());
return IsFastLiteralHelper(boilerplate, kMaxFastLiteralDepth,
&max_properties);
}
PretenureFlag AllocationSiteRef::GetPretenureMode() const {
AllowHandleDereference allow_handle_dereference;
return object<AllocationSite>()->GetPretenureMode();
}
void JSObjectRef::EnsureElementsTenured(const JSHeapBroker* broker) {
// TODO(jarin) Eventually, we will pretenure the boilerplates before
// the compilation job starts.
AllowHandleDereference allow_handle_dereference;
Handle<FixedArrayBase> object_elements =
elements(broker).object<FixedArrayBase>();
if (broker->isolate()->heap()->InNewSpace(*object_elements)) {
// If we would like to pretenure a fixed cow array, we must ensure that
// the array is already in old space, otherwise we'll create too many
// old-to-new-space pointers (overflowing the store buffer).
object_elements = Handle<FixedArrayBase>(
broker->isolate()->factory()->CopyAndTenureFixedCOWArray(
Handle<FixedArray>::cast(object_elements)));
object<JSObject>()->set_elements(*object_elements);
}
}
int MapRef::GetInObjectProperties() const {
AllowHandleDereference allow_handle_dereference;
return object<Map>()->GetInObjectProperties();
}
int MapRef::NumberOfOwnDescriptors() const {
AllowHandleDereference allow_handle_dereference;
return object<Map>()->NumberOfOwnDescriptors();
}
FieldIndex MapRef::GetFieldIndexFor(int i) const {
AllowHandleDereference allow_handle_dereference;
return FieldIndex::ForDescriptor(*object<Map>(), i);
}
int MapRef::instance_size() const {
AllowHandleDereference allow_handle_dereference;
return object<Map>()->instance_size();
}
InstanceType MapRef::instance_type() const {
AllowHandleDereference allow_handle_dereference;
return object<Map>()->instance_type();
}
PropertyDetails MapRef::GetPropertyDetails(int i) const {
AllowHandleDereference allow_handle_dereference;
return object<Map>()->instance_descriptors()->GetDetails(i);
}
NameRef MapRef::GetPropertyKey(const JSHeapBroker* broker, int i) const {
AllowHandleDereference allow_handle_dereference;
return NameRef(handle(object<Map>()->instance_descriptors()->GetKey(i),
broker->isolate()));
}
bool MapRef::IsJSArrayMap() const {
AllowHandleDereference allow_handle_dereference;
return object<Map>()->IsJSArrayMap();
}
bool MapRef::IsFixedCowArrayMap(const JSHeapBroker* broker) const {
AllowHandleDereference allow_handle_dereference;
return *object<Map>() == broker->isolate()->heap()->fixed_cow_array_map();
}
ElementsKind JSArrayRef::GetElementsKind() const {
AllowHandleDereference allow_handle_dereference;
return object<JSArray>()->GetElementsKind();
}
ObjectRef JSArrayRef::length(const JSHeapBroker* broker) const {
AllowHandleDereference allow_handle_dereference;
return ObjectRef(handle(object<JSArray>()->length(), broker->isolate()));
}
int FixedArrayBaseRef::length() const {
AllowHandleDereference allow_handle_dereference;
return object<FixedArrayBase>()->length();
}
bool FixedArrayRef::is_the_hole(const JSHeapBroker* broker, int i) const {
AllowHandleDereference allow_handle_dereference;
return object<FixedArray>()->is_the_hole(broker->isolate(), i);
}
ObjectRef FixedArrayRef::get(const JSHeapBroker* broker, int i) const {
AllowHandleDereference allow_handle_dereference;
return ObjectRef(handle(object<FixedArray>()->get(i), broker->isolate()));
}
bool FixedDoubleArrayRef::is_the_hole(int i) const {
AllowHandleDereference allow_handle_dereference;
return object<FixedDoubleArray>()->is_the_hole(i);
}
double FixedDoubleArrayRef::get_scalar(int i) const {
AllowHandleDereference allow_handle_dereference;
return object<FixedDoubleArray>()->get_scalar(i);
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -20,6 +20,7 @@ enum class OddballType : uint8_t {
kUndefined,
kNull,
kHole,
kUninitialized,
kOther, // Oddball, but none of the above.
kAny // Any Oddball.
};
......@@ -53,13 +54,22 @@ class HeapObjectType {
};
#define HEAP_BROKER_DATA_LIST(V) \
V(AllocationSite) \
V(Context) \
V(FeedbackVector) \
V(FixedArray) \
V(FixedArrayBase) \
V(FixedDoubleArray) \
V(HeapNumber) \
V(HeapObject) \
V(JSArray) \
V(JSFunction) \
V(JSObject) \
V(MutableHeapNumber) \
V(Name) \
V(NativeContext) \
V(ScriptContextTable)
V(ScriptContextTable) \
V(Map)
#define HEAP_BROKER_KIND_LIST(V) \
HEAP_BROKER_DATA_LIST(V) \
......@@ -105,6 +115,8 @@ class HeapObjectRef : public ObjectRef {
explicit HeapObjectRef(Handle<Object> object);
HeapObjectType type(const JSHeapBroker* broker) const;
MapRef map(const JSHeapBroker* broker) const;
private:
friend class JSHeapBroker;
};
......@@ -129,7 +141,20 @@ class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
Isolate* const isolate_;
};
class JSFunctionRef : public HeapObjectRef {
class JSObjectRef : public HeapObjectRef {
public:
explicit JSObjectRef(Handle<Object> object) : HeapObjectRef(object) {}
bool IsUnboxedDoubleField(FieldIndex index) const;
double RawFastDoublePropertyAt(FieldIndex index) const;
ObjectRef RawFastPropertyAt(const JSHeapBroker* broker,
FieldIndex index) const;
FixedArrayBaseRef elements(const JSHeapBroker* broker) const;
void EnsureElementsTenured(const JSHeapBroker* broker);
};
class JSFunctionRef : public JSObjectRef {
public:
explicit JSFunctionRef(Handle<Object> object);
bool HasBuiltinFunctionId() const;
......@@ -142,6 +167,12 @@ class HeapNumberRef : public HeapObjectRef {
double value() const;
};
class MutableHeapNumberRef : public HeapObjectRef {
public:
explicit MutableHeapNumberRef(Handle<Object> object);
double value() const;
};
class ContextRef : public HeapObjectRef {
public:
explicit ContextRef(Handle<Object> object);
......@@ -173,6 +204,73 @@ class ScriptContextTableRef : public HeapObjectRef {
base::Optional<LookupResult> lookup(const NameRef& name) const;
};
class FeedbackVectorRef : public HeapObjectRef {
public:
explicit FeedbackVectorRef(Handle<Object> object) : HeapObjectRef(object) {}
ObjectRef get(const JSHeapBroker* broker, FeedbackSlot slot) const;
};
class AllocationSiteRef : public HeapObjectRef {
public:
explicit AllocationSiteRef(Handle<HeapObject> object)
: HeapObjectRef(object) {}
JSObjectRef boilerplate(const JSHeapBroker* broker) const;
PretenureFlag GetPretenureMode() const;
bool IsFastLiteral(const JSHeapBroker* broker);
};
class MapRef : public HeapObjectRef {
public:
explicit MapRef(Handle<HeapObject> object) : HeapObjectRef(object) {}
int instance_size() const;
InstanceType instance_type() const;
int GetInObjectProperties() const;
int NumberOfOwnDescriptors() const;
PropertyDetails GetPropertyDetails(int i) const;
NameRef GetPropertyKey(const JSHeapBroker* broker, int i) const;
FieldIndex GetFieldIndexFor(int i) const;
bool IsJSArrayMap() const;
bool IsFixedCowArrayMap(const JSHeapBroker* broker) const;
};
class FixedArrayBaseRef : public HeapObjectRef {
public:
explicit FixedArrayBaseRef(Handle<HeapObject> object)
: HeapObjectRef(object) {}
int length() const;
};
class FixedArrayRef : public FixedArrayBaseRef {
public:
explicit FixedArrayRef(Handle<HeapObject> object)
: FixedArrayBaseRef(object) {}
bool is_the_hole(const JSHeapBroker* broker, int i) const;
ObjectRef get(const JSHeapBroker* broker, int i) const;
};
class FixedDoubleArrayRef : public FixedArrayBaseRef {
public:
explicit FixedDoubleArrayRef(Handle<HeapObject> object)
: FixedArrayBaseRef(object) {}
bool is_the_hole(int i) const;
double get_scalar(int i) const;
};
class JSArrayRef : public JSObjectRef {
public:
explicit JSArrayRef(Handle<Object> object) : JSObjectRef(object) {}
ElementsKind GetElementsKind() const;
ObjectRef length(const JSHeapBroker* broker) const;
};
} // namespace compiler
} // namespace internal
} // namespace v8
......
......@@ -164,6 +164,8 @@ Type::bitset BitsetType::Lub(HeapObjectType const& type) {
return kBigInt;
case ODDBALL_TYPE:
switch (type.oddball_type()) {
case OddballType::kNone:
break;
case OddballType::kHole:
return kHole;
case OddballType::kBoolean:
......@@ -172,14 +174,14 @@ Type::bitset BitsetType::Lub(HeapObjectType const& type) {
return kNull;
case OddballType::kUndefined:
return kUndefined;
case OddballType::kUninitialized:
case OddballType::kOther:
// TODO(neis): We should add a kOtherOddball type.
return kOtherInternal;
case OddballType::kAny:
return kOddball | kOtherInternal;
default:
UNREACHABLE();
}
UNREACHABLE();
case HEAP_NUMBER_TYPE:
return kNumber;
case JS_OBJECT_TYPE:
......
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