Commit 24c8f0b0 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Relax restrictions on JSCreate inlining.

No need to limit JSCreate inlining to JS_OBJECT_TYPE, since we can
handle everything that the FastNewObjectStub can deal with. Also we
don't need to restrict the number of inobject properties, as that is
already taken care of by the runtime anyways (limited by the initial
slack for the constructor).

And last but not least, we can of course inline allocations for
subclasses as long as the new.target is a JSFunction and it's initial
map's constructor points back to the target (same condition as for
the FastNewObjectStub fast case).

R=jarin@chromium.org
BUG=v8:4493
LOG=n

Review URL: https://codereview.chromium.org/1711883003

Cr-Commit-Position: refs/heads/master@{#34138}
parent a56af889
......@@ -108,17 +108,12 @@ Node* GetArgumentsFrameState(Node* frame_state) {
: frame_state;
}
// Maximum instance size for which allocations will be inlined.
const int kMaxInlineInstanceSize = 64 * kPointerSize;
// Checks whether allocation using the given constructor can be inlined.
bool IsAllocationInlineable(Handle<JSFunction> constructor) {
// TODO(bmeurer): Further relax restrictions on inlining, i.e.
// instance type and maybe instance size (inobject properties
// are limited anyways by the runtime).
return constructor->has_initial_map() &&
constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
constructor->initial_map()->instance_size() < kMaxInlineInstanceSize;
// Checks whether allocation using the given target and new.target can be
// inlined.
bool IsAllocationInlineable(Handle<JSFunction> target,
Handle<JSFunction> new_target) {
return new_target->has_initial_map() &&
new_target->initial_map()->constructor_or_backpointer() == *target;
}
// When initializing arrays, we'll unfold the loop if the number of
......@@ -230,30 +225,36 @@ Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
Node* const target = NodeProperties::GetValueInput(node, 0);
Type* const target_type = NodeProperties::GetType(target);
Node* const new_target = NodeProperties::GetValueInput(node, 1);
Type* const new_target_type = NodeProperties::GetType(new_target);
Node* const effect = NodeProperties::GetEffectInput(node);
// TODO(turbofan): Add support for NewTarget passed to JSCreate.
if (target != new_target) return NoChange();
// Extract constructor function.
// Extract constructor and original constructor function.
if (target_type->IsConstant() &&
target_type->AsConstant()->Value()->IsJSFunction()) {
new_target_type->IsConstant() &&
new_target_type->AsConstant()->Value()->IsJSFunction()) {
Handle<JSFunction> constructor =
Handle<JSFunction>::cast(target_type->AsConstant()->Value());
Handle<JSFunction> original_constructor =
Handle<JSFunction>::cast(new_target_type->AsConstant()->Value());
DCHECK(constructor->IsConstructor());
// Force completion of inobject slack tracking before
// generating code to finalize the instance size.
constructor->CompleteInobjectSlackTrackingIfActive();
DCHECK(original_constructor->IsConstructor());
// Check if we can inline the allocation.
if (IsAllocationInlineable(constructor)) {
// Compute instance size from initial map of {constructor}.
Handle<Map> initial_map(constructor->initial_map(), isolate());
if (IsAllocationInlineable(constructor, original_constructor)) {
// Force completion of inobject slack tracking before
// generating code to finalize the instance size.
original_constructor->CompleteInobjectSlackTrackingIfActive();
// Compute instance size from initial map of {original_constructor}.
Handle<Map> initial_map(original_constructor->initial_map(), isolate());
int const instance_size = initial_map->instance_size();
// Add a dependency on the {initial_map} to make sure that this code is
// deoptimized whenever the {initial_map} of the {constructor} changes.
// deoptimized whenever the {initial_map} of the {original_constructor}
// changes.
dependencies()->AssumeInitialMapCantChange(initial_map);
// Emit code to allocate the JSObject instance for the {constructor}.
// Emit code to allocate the JSObject instance for the
// {original_constructor}.
AllocationBuilder a(jsgraph(), effect, graph()->start());
a.Allocate(instance_size);
a.Store(AccessBuilder::ForMap(), initial_map);
......
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