Commit 6c620e53 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

Fix usage of literal cloning for large double arrays.

This fixes a corner case where the {FastCloneShallowArrayStub} was used
for literals that are backed by a double backing store and would exceed
limits for new-space allocations on 32-bit architectures. The stub in
question does not support such literals, callers must use the runtime.
Note that this fix is for Ignition as well as FullCodeGenerator.

R=rmcilroy@chromium.org
TEST=mjsunit/regress/regress-crbug-672792
BUG=chromium:672792

Review-Url: https://codereview.chromium.org/2570843002
Cr-Commit-Position: refs/heads/master@{#41713}
parent b02fd88d
......@@ -574,6 +574,14 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
set_depth(depth_acc);
}
bool ObjectLiteral::IsFastCloningSupported() const {
// FastCloneShallowObjectStub doesn't copy elements, and object literals don't
// support copy-on-write (COW) elements for now.
// TODO(mvstanton): make object literals support COW elements.
return fast_elements() && has_shallow_properties() &&
properties_count() <=
FastCloneShallowObjectStub::kMaximumClonedProperties;
}
void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
DCHECK_LT(first_spread_index_, 0);
......@@ -648,6 +656,11 @@ void ArrayLiteral::BuildConstantElements(Isolate* isolate) {
set_depth(depth_acc);
}
bool ArrayLiteral::IsFastCloningSupported() const {
return depth() <= 1 &&
values()->length() <=
FastCloneShallowArrayStub::kMaximumClonedElements;
}
void ArrayLiteral::AssignFeedbackVectorSlots(Isolate* isolate,
FeedbackVectorSpec* spec,
......
......@@ -1415,6 +1415,9 @@ class ObjectLiteral final : public MaterializedLiteral {
// marked expressions, no store code is emitted.
void CalculateEmitStore(Zone* zone);
// Determines whether the {FastCloneShallowObjectStub} can be used.
bool IsFastCloningSupported() const;
// Assemble bitfield of flags for the CreateObjectLiteral helper.
int ComputeFlags(bool disable_mementos = false) const {
int flags = fast_elements() ? kFastElements : kNoFlags;
......@@ -1558,6 +1561,9 @@ class ArrayLiteral final : public MaterializedLiteral {
// Populate the constant elements fixed array.
void BuildConstantElements(Isolate* isolate);
// Determines whether the {FastCloneShallowArrayStub} can be used.
bool IsFastCloningSupported() const;
// Assemble bitfield of flags for the CreateArrayLiteral helper.
int ComputeFlags(bool disable_mementos = false) const {
int flags = depth() == 1 ? kShallowElements : kNoFlags;
......
......@@ -2157,15 +2157,6 @@ void LoadIndexedInterceptorStub::GenerateAssembly(
slot, vector);
}
// static
bool FastCloneShallowObjectStub::IsSupported(ObjectLiteral* expr) {
// FastCloneShallowObjectStub doesn't copy elements, and object literals don't
// support copy-on-write (COW) elements for now.
// TODO(mvstanton): make object literals support COW elements.
return expr->fast_elements() && expr->has_shallow_properties() &&
expr->properties_count() <= kMaximumClonedProperties;
}
// static
int FastCloneShallowObjectStub::PropertiesCount(int literal_length) {
// This heuristic of setting empty literals to have
......
......@@ -20,7 +20,6 @@ namespace internal {
// Forward declarations.
class CodeStubAssembler;
class ObjectLiteral;
namespace compiler {
class CodeAssemblerLabel;
class CodeAssemblerState;
......@@ -923,6 +922,11 @@ class FastCloneRegExpStub final : public TurboFanCodeStub {
class FastCloneShallowArrayStub : public TurboFanCodeStub {
public:
// Maximum number of elements in copied array (chosen so that even an array
// backed by a double backing store will fit into new-space).
static const int kMaximumClonedElements =
JSArray::kInitialMaxFastElementArray * kPointerSize / kDoubleSize;
FastCloneShallowArrayStub(Isolate* isolate,
AllocationSiteMode allocation_site_mode)
: TurboFanCodeStub(isolate) {
......@@ -964,7 +968,6 @@ class FastCloneShallowObjectStub : public TurboFanCodeStub {
compiler::Node* closure, compiler::Node* literals_index,
compiler::Node* properties_count);
static bool IsSupported(ObjectLiteral* expr);
static int PropertiesCount(int literal_length);
int length() const { return LengthBits::decode(minor_key_); }
......
......@@ -162,7 +162,9 @@ bool IsFastLiteral(Handle<JSObject> boilerplate, int max_depth,
}
}
}
} else if (!boilerplate->HasFastDoubleElements()) {
} else if (boilerplate->HasFastDoubleElements()) {
if (elements->Size() > kMaxRegularHeapObjectSize) return false;
} else {
return false;
}
}
......
......@@ -378,10 +378,10 @@ void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
// Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
// initial length limit for arrays with "fast" elements kind.
// Use the FastCloneShallowArrayStub only for shallow boilerplates without
// properties up to the number of elements that the stubs can handle.
if ((p.flags() & ArrayLiteral::kShallowElements) != 0 &&
p.length() < JSArray::kInitialMaxFastElementArray) {
p.length() < FastCloneShallowArrayStub::kMaximumClonedElements) {
Callable callable = CodeFactory::FastCloneShallowArray(isolate());
ReplaceWithStubCall(node, callable, flags);
} else {
......
......@@ -5455,7 +5455,9 @@ static bool IsFastLiteral(Handle<JSObject> boilerplate,
}
}
}
} else if (!boilerplate->HasFastDoubleElements()) {
} else if (boilerplate->HasFastDoubleElements()) {
if (elements->Size() > kMaxRegularHeapObjectSize) return false;
} else {
return false;
}
}
......
......@@ -176,15 +176,13 @@ void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime(
ObjectLiteral* expr) const {
return masm()->serializer_enabled() ||
!FastCloneShallowObjectStub::IsSupported(expr);
return masm()->serializer_enabled() || !expr->IsFastCloningSupported();
}
bool FullCodeGenerator::MustCreateArrayLiteralWithRuntime(
ArrayLiteral* expr) const {
return expr->depth() > 1 ||
expr->values()->length() > JSArray::kInitialMaxFastElementArray;
return !expr->IsFastCloningSupported();
}
void FullCodeGenerator::Initialize(uintptr_t stack_limit) {
......
......@@ -1591,9 +1591,9 @@ void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
}
void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// Copy the literal boilerplate.
// Deep-copy the literal boilerplate.
uint8_t flags = CreateObjectLiteralFlags::Encode(
FastCloneShallowObjectStub::IsSupported(expr),
expr->IsFastCloningSupported(),
FastCloneShallowObjectStub::PropertiesCount(expr->properties_count()),
expr->ComputeFlags());
// If constant properties is an empty fixed array, use our cached
......@@ -1769,12 +1769,8 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
// Deep-copy the literal boilerplate.
int runtime_flags = expr->ComputeFlags();
bool use_fast_shallow_clone =
(runtime_flags & ArrayLiteral::kShallowElements) != 0 &&
expr->values()->length() <= JSArray::kInitialMaxFastElementArray;
uint8_t flags =
CreateArrayLiteralFlags::Encode(use_fast_shallow_clone, runtime_flags);
uint8_t flags = CreateArrayLiteralFlags::Encode(
expr->IsFastCloningSupported(), expr->ComputeFlags());
builder()->CreateArrayLiteral(expr->constant_elements(),
expr->literal_index(), flags);
Register index, literal;
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// Generate a function {f} containing a large array literal of doubles.
eval("function f() { return [" + String("0.1,").repeat(65535) + "] }");
// Running the function once will initialize the boilerplate.
assertEquals(65535, f().length);
// Running the function again will perform cloning.
assertEquals(65535, f().length);
// Running the function as optimized code next.
%OptimizeFunctionOnNextCall(f);
assertEquals(65535, f().length);
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