Commit 4d2b197d authored by Peter Marshall's avatar Peter Marshall Committed by Commit Bot

[runtime] Set arguments limit to FixedArray::kMaxLength

Right now, this is the limit implicitly imposed for spread/apply calls
as to actually do a spread/apply call through CallVarargs, you need to
pass a FixedArray with the args to be pushed.

Likewise, turbofan can only materialize an arguments object with a
backing store of length FixedArray::kMaxLength.

The practical limit that users will actually hit is the stack - this
change doesn't change that, it just documents what the actual limit is.

This would actually allow an embedder/custom fork to increase stack
size and still be able to make spread/apply calls with a large number
of args.

Change-Id: If5e66a61ed3f9df36031eb098646d48fc2ca2507
Reviewed-on: https://chromium-review.googlesource.com/c/1367451Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58119}
parent 2f55187e
...@@ -194,6 +194,8 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike( ...@@ -194,6 +194,8 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike(
TNode<Int32T> length = var_length.value(); TNode<Int32T> length = var_length.value();
{ {
Label normalize_done(this); Label normalize_done(this);
CSA_ASSERT(this, Int32LessThanOrEqual(
length, Int32Constant(FixedArray::kMaxLength)));
GotoIfNot(Word32Equal(length, Int32Constant(0)), &normalize_done); GotoIfNot(Word32Equal(length, Int32Constant(0)), &normalize_done);
// Make sure we don't accidentally pass along the // Make sure we don't accidentally pass along the
// empty_fixed_double_array since the tailed-called stubs cannot handle // empty_fixed_double_array since the tailed-called stubs cannot handle
...@@ -239,6 +241,8 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructDoubleVarargs( ...@@ -239,6 +241,8 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructDoubleVarargs(
TNode<Int32T> args_count, TNode<Context> context, TNode<Int32T> kind) { TNode<Int32T> args_count, TNode<Context> context, TNode<Int32T> kind) {
const ElementsKind new_kind = PACKED_ELEMENTS; const ElementsKind new_kind = PACKED_ELEMENTS;
const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER; const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
CSA_ASSERT(this, Int32LessThanOrEqual(length,
Int32Constant(FixedArray::kMaxLength)));
TNode<IntPtrT> intptr_length = ChangeInt32ToIntPtr(length); TNode<IntPtrT> intptr_length = ChangeInt32ToIntPtr(length);
CSA_ASSERT(this, WordNotEqual(intptr_length, IntPtrConstant(0))); CSA_ASSERT(this, WordNotEqual(intptr_length, IntPtrConstant(0)));
...@@ -329,6 +333,8 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread( ...@@ -329,6 +333,8 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread(
{ {
TNode<FixedArrayBase> elements = var_elements.value(); TNode<FixedArrayBase> elements = var_elements.value();
TNode<Int32T> length = var_length.value(); TNode<Int32T> length = var_length.value();
CSA_ASSERT(this, Int32LessThanOrEqual(
length, Int32Constant(FixedArray::kMaxLength)));
if (new_target == nullptr) { if (new_target == nullptr) {
Callable callable = CodeFactory::CallVarargs(isolate()); Callable callable = CodeFactory::CallVarargs(isolate());
......
...@@ -165,8 +165,10 @@ class TypeCache final { ...@@ -165,8 +165,10 @@ class TypeCache final {
Type const kJSDateYearType = Type const kJSDateYearType =
Type::Union(Type::SignedSmall(), Type::NaN(), zone()); Type::Union(Type::SignedSmall(), Type::NaN(), zone());
// The valid number of arguments for JavaScript functions. // The valid number of arguments for JavaScript functions. We can never
Type const kArgumentsLengthType = Type::Unsigned30(); // materialize more than the max size of a fixed array, because we require a
// fixed array in spread/apply calls.
Type const kArgumentsLengthType = CreateRange(0.0, FixedArray::kMaxLength);
// The JSArrayIterator::kind property always contains an integer in the // The JSArrayIterator::kind property always contains an integer in the
// range [0, 2], representing the possible IterationKinds. // range [0, 2], representing the possible IterationKinds.
......
...@@ -700,7 +700,7 @@ Type Typer::Visitor::TypeParameter(Node* node) { ...@@ -700,7 +700,7 @@ Type Typer::Visitor::TypeParameter(Node* node) {
return Type::Union(Type::Receiver(), Type::Undefined(), typer_->zone()); return Type::Union(Type::Receiver(), Type::Undefined(), typer_->zone());
} }
} else if (index == Linkage::GetJSCallArgCountParamIndex(parameter_count)) { } else if (index == Linkage::GetJSCallArgCountParamIndex(parameter_count)) {
return Type::Range(0.0, Code::kMaxArguments, typer_->zone()); return Type::Range(0.0, FixedArray::kMaxLength, typer_->zone());
} else if (index == Linkage::GetJSCallContextParamIndex(parameter_count)) { } else if (index == Linkage::GetJSCallContextParamIndex(parameter_count)) {
return Type::OtherInternal(); return Type::OtherInternal();
} }
......
...@@ -1258,7 +1258,8 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { ...@@ -1258,7 +1258,8 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
break; break;
case IrOpcode::kNewArgumentsElements: case IrOpcode::kNewArgumentsElements:
CheckValueInputIs(node, 0, Type::ExternalPointer()); CheckValueInputIs(node, 0, Type::ExternalPointer());
CheckValueInputIs(node, 1, Type::Unsigned30()); CheckValueInputIs(node, 1,
Type::Range(0.0, FixedArray::kMaxLength, zone));
CheckTypeIs(node, Type::OtherInternal()); CheckTypeIs(node, Type::OtherInternal());
break; break;
case IrOpcode::kNewConsString: case IrOpcode::kNewConsString:
......
...@@ -71,6 +71,7 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke( ...@@ -71,6 +71,7 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(
Execution::Target execution_target) { Execution::Target execution_target) {
RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kInvoke); RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kInvoke);
DCHECK(!receiver->IsJSGlobalObject()); DCHECK(!receiver->IsJSGlobalObject());
DCHECK_LE(argc, FixedArray::kMaxLength);
#ifdef USE_SIMULATOR #ifdef USE_SIMULATOR
// Simulators use separate stacks for C++ and JS. JS stack overflow checks // Simulators use separate stacks for C++ and JS. JS stack overflow checks
......
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