[csa][cleanup] introduce ArrayCreate and Construct to match spec

In preparation of porting Array.of to Torque, restructure the code and
add Construct() and ArrayCreate() to match spec text.
As a drive-by change, add and improve a bunch of CSA types and remove
direct usage of JSConstruct.

Bug: v8:8321

Change-Id: I445093388214d5b17b6dbc8d24c76ee296163071
Reviewed-on: https://chromium-review.googlesource.com/c/1296487
Reviewed-by: Mathias Bynens <mathias@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56928}
This commit is contained in:
Tobias Tebbi 2018-10-23 21:21:45 +02:00 committed by Commit Bot
parent f289f1cafb
commit bada4d5ccc
7 changed files with 179 additions and 151 deletions

View File

@ -869,10 +869,9 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
BIND(&runtime);
{
// 5. Let A be ? ArraySpeciesCreate(O, len).
Node* constructor =
CallRuntime(Runtime::kArraySpeciesConstructor, context(), o());
a_.Bind(ConstructJS(CodeFactory::Construct(isolate()), context(),
constructor, len));
TNode<JSReceiver> constructor =
CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context(), o()));
a_.Bind(Construct(context(), constructor, len));
Goto(&fully_spec_compliant_);
}
@ -918,10 +917,9 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
BIND(&runtime);
{
// 5. Let A be ? ArraySpeciesCreate(O, len).
Node* constructor =
CallRuntime(Runtime::kArraySpeciesConstructor, context(), o());
a_.Bind(ConstructJS(CodeFactory::Construct(isolate()), context(),
constructor, len));
TNode<JSReceiver> constructor =
CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context(), o()));
a_.Bind(Construct(context(), constructor, len));
Goto(&fully_spec_compliant_);
}
@ -1424,7 +1422,7 @@ TF_BUILTIN(ArrayPrototypeSlice, ArrayPrototypeSliceCodeStubAssembler) {
BIND(&relative_end_done);
// 11. Let count be max(final k, 0).
Node* count =
TNode<Number> count =
NumberMax(NumberSub(final.value(), k.value()), NumberConstant(0));
// Handle FAST_ELEMENTS
@ -1437,10 +1435,9 @@ TF_BUILTIN(ArrayPrototypeSlice, ArrayPrototypeSliceCodeStubAssembler) {
// 13. ReturnIfAbrupt(A).
BIND(&non_fast);
Node* constructor =
CallRuntime(Runtime::kArraySpeciesConstructor, context, o.value());
Node* a = ConstructJS(CodeFactory::Construct(isolate()), context, constructor,
count);
TNode<JSReceiver> constructor =
CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o.value()));
TNode<JSReceiver> a = Construct(context, constructor, count);
// 14. Let n be 0.
VARIABLE(n, MachineRepresentation::kTagged);
@ -1471,7 +1468,7 @@ TF_BUILTIN(ArrayPrototypeSlice, ArrayPrototypeSliceCodeStubAssembler) {
// 16. Let setStatus be Set(A, "length", n, true).
// 17. ReturnIfAbrupt(setStatus).
SetPropertyStrict(context, CAST(a), CodeStubAssembler::LengthStringConstant(),
SetPropertyStrict(context, a, CodeStubAssembler::LengthStringConstant(),
CAST(n.value()));
args.PopAndReturn(a);
}
@ -1863,8 +1860,7 @@ class ArrayPopulatorAssembler : public CodeStubAssembler {
BIND(&is_constructor);
{
array = CAST(
ConstructJS(CodeFactory::Construct(isolate()), context, receiver));
array = Construct(context, CAST(receiver));
Goto(&done);
}
@ -1896,49 +1892,13 @@ class ArrayPopulatorAssembler : public CodeStubAssembler {
BIND(&is_constructor);
{
array = CAST(ConstructJS(CodeFactory::Construct(isolate()), context,
receiver, length));
array = Construct(context, CAST(receiver), length);
Goto(&done);
}
BIND(&is_not_constructor);
{
Label allocate_js_array(this);
Label next(this), runtime(this, Label::kDeferred);
TNode<Smi> limit = SmiConstant(JSArray::kInitialMaxFastElementArray);
CSA_ASSERT_BRANCH(this, [=](Label* ok, Label* not_ok) {
BranchIfNumberRelationalComparison(Operation::kGreaterThanOrEqual,
length, SmiConstant(0), ok, not_ok);
});
// This check also transitively covers the case where length is too big
// to be representable by a SMI and so is not usable with
// AllocateJSArray.
BranchIfNumberRelationalComparison(Operation::kGreaterThanOrEqual, length,
limit, &runtime, &next);
BIND(&runtime);
{
TNode<Context> native_context = LoadNativeContext(context);
TNode<JSFunction> array_function = CAST(
LoadContextElement(native_context, Context::ARRAY_FUNCTION_INDEX));
array = CallRuntime(Runtime::kNewArray, context, array_function, length,
array_function, UndefinedConstant());
Goto(&done);
}
BIND(&next);
CSA_ASSERT(this, TaggedIsSmi(length));
TNode<Map> array_map = CAST(LoadContextElement(
context, Context::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX));
// TODO(delphick): Consider using
// AllocateUninitializedJSArrayWithElements to avoid initializing an
// array and then writing over it.
array = CAST(AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, length,
SmiConstant(0), nullptr,
ParameterMode::SMI_PARAMETERS));
array = ArrayCreate(context, length);
Goto(&done);
}
@ -2189,21 +2149,38 @@ TF_BUILTIN(ArrayOf, ArrayPopulatorAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
CodeStubArguments args(this, length, nullptr, ParameterMode::SMI_PARAMETERS);
TNode<Object> receiver = args.GetReceiver();
TNode<Object> array = ConstructArrayLike(context, args.GetReceiver(), length);
TVARIABLE(Object, array);
Label is_constructor(this), is_not_constructor(this), fill_array(this);
GotoIf(TaggedIsSmi(receiver), &is_not_constructor);
Branch(IsConstructor(CAST(receiver)), &is_constructor, &is_not_constructor);
BIND(&is_constructor);
{
array = Construct(context, CAST(receiver), length);
Goto(&fill_array);
}
BIND(&is_not_constructor);
{
array = ArrayCreate(context, length);
Goto(&fill_array);
}
BIND(&fill_array);
// TODO(delphick): Avoid using CreateDataProperty on the fast path.
BuildFastLoop(SmiConstant(0), length,
[=](Node* index) {
[&](Node* index) {
CallRuntime(
Runtime::kCreateDataProperty, context,
static_cast<Node*>(array), index,
static_cast<Node*>(array.value()), index,
args.AtIndex(index, ParameterMode::SMI_PARAMETERS));
},
1, ParameterMode::SMI_PARAMETERS, IndexAdvanceMode::kPost);
GenerateSetLength(context, array, length);
args.PopAndReturn(array);
GenerateSetLength(context, array.value(), length);
args.PopAndReturn(array.value());
}
// ES #sec-get-%typedarray%.prototype.find
@ -3839,38 +3816,37 @@ TF_BUILTIN(FlatMapIntoArray, ArrayFlattenAssembler) {
// https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flat
TF_BUILTIN(ArrayPrototypeFlat, CodeStubAssembler) {
Node* const argc =
TNode<IntPtrT> const argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = args.GetReceiver();
Node* const depth = args.GetOptionalArgumentValue(0);
TNode<Context> const context = CAST(Parameter(Descriptor::kContext));
TNode<Object> const receiver = args.GetReceiver();
TNode<Object> const depth = args.GetOptionalArgumentValue(0);
// 1. Let O be ? ToObject(this value).
Node* const o = ToObject_Inline(CAST(context), CAST(receiver));
TNode<JSReceiver> const o = ToObject_Inline(context, receiver);
// 2. Let sourceLen be ? ToLength(? Get(O, "length")).
Node* const source_length =
TNode<Number> const source_length =
ToLength_Inline(context, GetProperty(context, o, LengthStringConstant()));
// 3. Let depthNum be 1.
VARIABLE(var_depth_num, MachineRepresentation::kTagged, SmiConstant(1));
TVARIABLE(Number, var_depth_num, SmiConstant(1));
// 4. If depth is not undefined, then
Label done(this);
GotoIf(IsUndefined(depth), &done);
{
// a. Set depthNum to ? ToInteger(depth).
var_depth_num.Bind(ToInteger_Inline(context, depth));
var_depth_num = ToInteger_Inline(context, depth);
Goto(&done);
}
BIND(&done);
// 5. Let A be ? ArraySpeciesCreate(O, 0).
Node* const constructor =
CallRuntime(Runtime::kArraySpeciesConstructor, context, o);
Node* const a = ConstructJS(CodeFactory::Construct(isolate()), context,
constructor, SmiConstant(0));
TNode<JSReceiver> const constructor =
CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o));
Node* const a = Construct(context, constructor, SmiConstant(0));
// 6. Perform ? FlattenIntoArray(A, O, sourceLen, 0, depthNum).
CallBuiltin(Builtins::kFlattenIntoArray, context, a, o, source_length,
@ -3882,33 +3858,32 @@ TF_BUILTIN(ArrayPrototypeFlat, CodeStubAssembler) {
// https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatMap
TF_BUILTIN(ArrayPrototypeFlatMap, CodeStubAssembler) {
Node* const argc =
TNode<IntPtrT> const argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = args.GetReceiver();
Node* const mapper_function = args.GetOptionalArgumentValue(0);
TNode<Context> const context = CAST(Parameter(Descriptor::kContext));
TNode<Object> const receiver = args.GetReceiver();
TNode<Object> const mapper_function = args.GetOptionalArgumentValue(0);
// 1. Let O be ? ToObject(this value).
Node* const o = ToObject_Inline(CAST(context), CAST(receiver));
TNode<JSReceiver> const o = ToObject_Inline(context, receiver);
// 2. Let sourceLen be ? ToLength(? Get(O, "length")).
Node* const source_length =
TNode<Number> const source_length =
ToLength_Inline(context, GetProperty(context, o, LengthStringConstant()));
// 3. If IsCallable(mapperFunction) is false, throw a TypeError exception.
Label if_not_callable(this, Label::kDeferred);
GotoIf(TaggedIsSmi(mapper_function), &if_not_callable);
GotoIfNot(IsCallable(mapper_function), &if_not_callable);
GotoIfNot(IsCallable(CAST(mapper_function)), &if_not_callable);
// 4. If thisArg is present, let T be thisArg; else let T be undefined.
Node* const t = args.GetOptionalArgumentValue(1);
TNode<Object> const t = args.GetOptionalArgumentValue(1);
// 5. Let A be ? ArraySpeciesCreate(O, 0).
Node* const constructor =
CallRuntime(Runtime::kArraySpeciesConstructor, context, o);
Node* const a = ConstructJS(CodeFactory::Construct(isolate()), context,
constructor, SmiConstant(0));
TNode<JSReceiver> const constructor =
CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o));
TNode<JSReceiver> const a = Construct(context, constructor, SmiConstant(0));
// 6. Perform ? FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, T).
CallBuiltin(Builtins::kFlatMapIntoArray, context, a, o, source_length,

View File

@ -114,7 +114,7 @@ TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const constructor = Parameter(Descriptor::kConstructor);
Node* const debug_event = Parameter(Descriptor::kDebugEvent);
Node* const native_context = LoadNativeContext(context);
TNode<Context> const native_context = LoadNativeContext(context);
Label if_not_constructor(this, Label::kDeferred),
if_notcallable(this, Label::kDeferred), if_fast_promise_capability(this),
@ -164,11 +164,10 @@ TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) {
native_context, Context::PROMISE_GET_CAPABILITIES_EXECUTOR_SHARED_FUN);
Node* function_map = LoadContextElement(
native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
Node* executor = AllocateFunctionWithMapAndContext(
function_map, executor_info, executor_context);
TNode<JSFunction> executor = CAST(AllocateFunctionWithMapAndContext(
function_map, executor_info, executor_context));
Node* promise = ConstructJS(CodeFactory::Construct(isolate()),
native_context, constructor, executor);
Node* promise = Construct(native_context, CAST(constructor), executor);
StoreObjectField(capability, PromiseCapability::kPromiseOffset, promise);
Node* resolve =

View File

@ -2069,9 +2069,9 @@ TNode<Object> RegExpBuiltinsAssembler::MatchAllIterator(
BIND(&if_slow_regexp);
{
// a. Let C be ? SpeciesConstructor(R, %RegExp%).
TNode<Object> regexp_fun =
LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX);
TNode<Object> species_constructor =
TNode<JSFunction> regexp_fun = CAST(
LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX));
TNode<JSReceiver> species_constructor =
SpeciesConstructor(native_context, maybe_regexp, regexp_fun);
// b. Let flags be ? ToString(? Get(R, "flags")).
@ -2081,8 +2081,7 @@ TNode<Object> RegExpBuiltinsAssembler::MatchAllIterator(
// c. Let matcher be ? Construct(C, « R, flags »).
var_matcher =
CAST(ConstructJS(CodeFactory::Construct(isolate()), context,
species_constructor, maybe_regexp, flags_string));
Construct(context, species_constructor, maybe_regexp, flags_string);
// d. Let global be ? ToBoolean(? Get(matcher, "global")).
var_global = UncheckedCast<Int32T>(

View File

@ -276,8 +276,7 @@ TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) {
BIND(&allocate_off_heap);
{
GotoIf(IsFalse(initialize), &allocate_off_heap_no_init);
var_buffer = CAST(ConstructJS(CodeFactory::Construct(isolate()), context,
default_constructor, byte_length));
var_buffer = CAST(Construct(context, default_constructor, byte_length));
Goto(&attach_buffer);
}
@ -522,7 +521,7 @@ void TypedArrayBuiltinsAssembler::ConstructByTypedArray(
BIND(&if_buffernotshared);
{
buffer_constructor =
CAST(SpeciesConstructor(context, source_buffer, default_constructor));
SpeciesConstructor(context, source_buffer, default_constructor);
// TODO(petermarshall): Throw on detached typedArray.
GotoIfNot(IsDetachedBuffer(source_buffer), &construct);
source_length = SmiConstant(0);
@ -871,7 +870,7 @@ TNode<IntPtrT> TypedArrayBuiltinsAssembler::GetTypedArrayElementSize(
return element_size.value();
}
TNode<Object> TypedArrayBuiltinsAssembler::GetDefaultConstructor(
TNode<JSFunction> TypedArrayBuiltinsAssembler::GetDefaultConstructor(
TNode<Context> context, TNode<JSTypedArray> exemplar) {
TVARIABLE(IntPtrT, context_slot);
TNode<Word32T> elements_kind = LoadElementsKind(exemplar);
@ -882,17 +881,19 @@ TNode<Object> TypedArrayBuiltinsAssembler::GetDefaultConstructor(
context_slot = IntPtrConstant(typed_array_function_index);
});
return LoadContextElement(LoadNativeContext(context), context_slot.value());
return CAST(
LoadContextElement(LoadNativeContext(context), context_slot.value()));
}
TNode<Object> TypedArrayBuiltinsAssembler::TypedArraySpeciesConstructor(
TNode<JSReceiver> TypedArrayBuiltinsAssembler::TypedArraySpeciesConstructor(
TNode<Context> context, TNode<JSTypedArray> exemplar) {
TVARIABLE(Object, var_constructor);
TVARIABLE(JSReceiver, var_constructor);
Label slow(this), done(this);
// Let defaultConstructor be the intrinsic object listed in column one of
// Table 52 for exemplar.[[TypedArrayName]].
TNode<Object> default_constructor = GetDefaultConstructor(context, exemplar);
TNode<JSFunction> default_constructor =
GetDefaultConstructor(context, exemplar);
var_constructor = default_constructor;
Node* map = LoadMap(exemplar);
@ -912,12 +913,12 @@ TNode<JSTypedArray> TypedArrayBuiltinsAssembler::SpeciesCreateByArrayBuffer(
TNode<JSArrayBuffer> buffer, TNode<Number> byte_offset, TNode<Smi> len,
const char* method_name) {
// Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor).
TNode<Object> constructor = TypedArraySpeciesConstructor(context, exemplar);
TNode<JSReceiver> constructor =
TypedArraySpeciesConstructor(context, exemplar);
// Let newTypedArray be ? Construct(constructor, argumentList).
TNode<Object> new_object =
CAST(ConstructJS(CodeFactory::Construct(isolate()), context, constructor,
buffer, byte_offset, len));
TNode<JSReceiver> new_object =
Construct(context, constructor, buffer, byte_offset, len);
// Perform ? ValidateTypedArray(newTypedArray).
return ValidateTypedArray(context, new_object, method_name);
@ -929,8 +930,8 @@ TNode<JSTypedArray> TypedArrayBuiltinsAssembler::SpeciesCreateByLength(
CSA_ASSERT(this, TaggedIsPositiveSmi(len));
// Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor).
TNode<HeapObject> constructor =
CAST(TypedArraySpeciesConstructor(context, exemplar));
TNode<JSReceiver> constructor =
TypedArraySpeciesConstructor(context, exemplar);
return CreateByLength(context, constructor, len, method_name);
}

View File

@ -73,10 +73,10 @@ class TypedArrayBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
JSTypedArray::kBufferOffset);
}
TNode<Object> GetDefaultConstructor(TNode<Context> context,
TNode<JSFunction> GetDefaultConstructor(TNode<Context> context,
TNode<JSTypedArray> exemplar);
TNode<Object> TypedArraySpeciesConstructor(TNode<Context> context,
TNode<JSReceiver> TypedArraySpeciesConstructor(TNode<Context> context,
TNode<JSTypedArray> exemplar);
TNode<JSTypedArray> SpeciesCreateByArrayBuffer(TNode<Context> context,

View File

@ -665,42 +665,42 @@ TNode<Smi> CodeStubAssembler::TrySmiSub(TNode<Smi> lhs, TNode<Smi> rhs,
}
}
TNode<Object> CodeStubAssembler::NumberMax(SloppyTNode<Object> a,
SloppyTNode<Object> b) {
TNode<Number> CodeStubAssembler::NumberMax(SloppyTNode<Number> a,
SloppyTNode<Number> b) {
// TODO(danno): This could be optimized by specifically handling smi cases.
VARIABLE(result, MachineRepresentation::kTagged);
TVARIABLE(Number, result);
Label done(this), greater_than_equal_a(this), greater_than_equal_b(this);
GotoIfNumberGreaterThanOrEqual(a, b, &greater_than_equal_a);
GotoIfNumberGreaterThanOrEqual(b, a, &greater_than_equal_b);
result.Bind(NanConstant());
result = NanConstant();
Goto(&done);
BIND(&greater_than_equal_a);
result.Bind(a);
result = a;
Goto(&done);
BIND(&greater_than_equal_b);
result.Bind(b);
result = b;
Goto(&done);
BIND(&done);
return TNode<Object>::UncheckedCast(result.value());
return result.value();
}
TNode<Object> CodeStubAssembler::NumberMin(SloppyTNode<Object> a,
SloppyTNode<Object> b) {
TNode<Number> CodeStubAssembler::NumberMin(SloppyTNode<Number> a,
SloppyTNode<Number> b) {
// TODO(danno): This could be optimized by specifically handling smi cases.
VARIABLE(result, MachineRepresentation::kTagged);
TVARIABLE(Number, result);
Label done(this), greater_than_equal_a(this), greater_than_equal_b(this);
GotoIfNumberGreaterThanOrEqual(a, b, &greater_than_equal_a);
GotoIfNumberGreaterThanOrEqual(b, a, &greater_than_equal_b);
result.Bind(NanConstant());
result = NanConstant();
Goto(&done);
BIND(&greater_than_equal_a);
result.Bind(b);
result = b;
Goto(&done);
BIND(&greater_than_equal_b);
result.Bind(a);
result = a;
Goto(&done);
BIND(&done);
return TNode<Object>::UncheckedCast(result.value());
return result.value();
}
TNode<IntPtrT> CodeStubAssembler::ConvertToRelativeIndex(
@ -12314,11 +12314,11 @@ TNode<Object> CodeStubAssembler::GetSuperConstructor(
return result.value();
}
TNode<Object> CodeStubAssembler::SpeciesConstructor(
TNode<JSReceiver> CodeStubAssembler::SpeciesConstructor(
SloppyTNode<Context> context, SloppyTNode<Object> object,
SloppyTNode<Object> default_constructor) {
SloppyTNode<JSReceiver> default_constructor) {
Isolate* isolate = this->isolate();
TVARIABLE(Object, var_result, default_constructor);
TVARIABLE(JSReceiver, var_result, default_constructor);
// 2. Let C be ? Get(O, "constructor").
TNode<Object> constructor =
@ -12343,7 +12343,7 @@ TNode<Object> CodeStubAssembler::SpeciesConstructor(
Label throw_error(this);
GotoIf(TaggedIsSmi(species), &throw_error);
GotoIfNot(IsConstructorMap(LoadMap(CAST(species))), &throw_error);
var_result = species;
var_result = CAST(species);
Goto(&out);
// 8. Throw a TypeError exception.
@ -12687,22 +12687,20 @@ Node* CodeStubAssembler::AllocateJSIteratorResultForEntry(Node* context,
return result;
}
Node* CodeStubAssembler::ArraySpeciesCreate(TNode<Context> context,
TNode<JSReceiver> CodeStubAssembler::ArraySpeciesCreate(TNode<Context> context,
TNode<Object> o,
TNode<Number> len) {
Node* constructor =
CallRuntime(Runtime::kArraySpeciesConstructor, context, o);
return ConstructJS(CodeFactory::Construct(isolate()), context, constructor,
len);
TNode<JSReceiver> constructor =
CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o));
return Construct(context, constructor, len);
}
Node* CodeStubAssembler::InternalArrayCreate(TNode<Context> context,
TNode<JSReceiver> CodeStubAssembler::InternalArrayCreate(TNode<Context> context,
TNode<Number> len) {
Node* native_context = LoadNativeContext(context);
Node* const constructor = LoadContextElement(
native_context, Context::INTERNAL_ARRAY_FUNCTION_INDEX);
return ConstructJS(CodeFactory::Construct(isolate()), context, constructor,
len);
TNode<Context> native_context = LoadNativeContext(context);
TNode<JSReceiver> constructor = CAST(LoadContextElement(
native_context, Context::INTERNAL_ARRAY_FUNCTION_INDEX));
return Construct(context, constructor, len);
}
Node* CodeStubAssembler::IsDetachedBuffer(Node* buffer) {
@ -13292,5 +13290,50 @@ void CodeStubAssembler::InitializeFunctionContext(Node* native_context,
native_context);
}
TNode<JSArray> CodeStubAssembler::ArrayCreate(TNode<Context> context,
TNode<Number> length) {
TVARIABLE(JSArray, array);
Label allocate_js_array(this);
Label done(this), next(this), runtime(this, Label::kDeferred);
TNode<Smi> limit = SmiConstant(JSArray::kInitialMaxFastElementArray);
CSA_ASSERT_BRANCH(this, [=](Label* ok, Label* not_ok) {
BranchIfNumberRelationalComparison(Operation::kGreaterThanOrEqual, length,
SmiConstant(0), ok, not_ok);
});
// This check also transitively covers the case where length is too big
// to be representable by a SMI and so is not usable with
// AllocateJSArray.
BranchIfNumberRelationalComparison(Operation::kGreaterThanOrEqual, length,
limit, &runtime, &next);
BIND(&runtime);
{
TNode<Context> native_context = LoadNativeContext(context);
TNode<JSFunction> array_function =
CAST(LoadContextElement(native_context, Context::ARRAY_FUNCTION_INDEX));
array = CAST(CallRuntime(Runtime::kNewArray, context, array_function,
length, array_function, UndefinedConstant()));
Goto(&done);
}
BIND(&next);
CSA_ASSERT(this, TaggedIsSmi(length));
TNode<Map> array_map = CAST(LoadContextElement(
context, Context::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX));
// TODO(delphick): Consider using
// AllocateUninitializedJSArrayWithElements to avoid initializing an
// array and then writing over it.
array = CAST(AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, length,
SmiConstant(0), nullptr,
ParameterMode::SMI_PARAMETERS));
Goto(&done);
BIND(&done);
return array.value();
}
} // namespace internal
} // namespace v8

View File

@ -503,9 +503,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<Float64T> Float64RoundToEven(SloppyTNode<Float64T> x);
TNode<Float64T> Float64Trunc(SloppyTNode<Float64T> x);
// Select the minimum of the two provided Number values.
TNode<Object> NumberMax(SloppyTNode<Object> left, SloppyTNode<Object> right);
TNode<Number> NumberMax(SloppyTNode<Number> left, SloppyTNode<Number> right);
// Select the minimum of the two provided Number values.
TNode<Object> NumberMin(SloppyTNode<Object> left, SloppyTNode<Object> right);
TNode<Number> NumberMin(SloppyTNode<Number> left, SloppyTNode<Number> right);
// After converting an index to an integer, calculate a relative index: if
// index < 0, max(length + index, 0); else min(index, length)
@ -705,6 +705,13 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
callable, receiver, args...));
}
template <class... TArgs>
TNode<JSReceiver> Construct(TNode<Context> context,
TNode<JSReceiver> new_target, TArgs... args) {
return CAST(ConstructJS(CodeFactory::Construct(isolate()), context,
new_target, implicit_cast<TNode<Object>>(args)...));
}
template <class A, class F, class G>
TNode<A> Select(SloppyTNode<BoolT> condition, const F& true_body,
const G& false_body) {
@ -1544,9 +1551,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* AllocateJSIteratorResult(Node* context, Node* value, Node* done);
Node* AllocateJSIteratorResultForEntry(Node* context, Node* key, Node* value);
Node* ArraySpeciesCreate(TNode<Context> context, TNode<Object> originalArray,
TNode<JSReceiver> ArraySpeciesCreate(TNode<Context> context,
TNode<Object> originalArray,
TNode<Number> len);
TNode<JSReceiver> InternalArrayCreate(TNode<Context> context,
TNode<Number> len);
Node* InternalArrayCreate(TNode<Context> context, TNode<Number> len);
void FillFixedArrayWithValue(ElementsKind kind, Node* array, Node* from_index,
Node* to_index, RootIndex value_root_index,
@ -2966,9 +2975,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<Object> GetSuperConstructor(SloppyTNode<Context> context,
SloppyTNode<JSFunction> active_function);
TNode<Object> SpeciesConstructor(SloppyTNode<Context> context,
SloppyTNode<Object> object,
SloppyTNode<Object> default_constructor);
TNode<JSReceiver> SpeciesConstructor(
SloppyTNode<Context> context, SloppyTNode<Object> object,
SloppyTNode<JSReceiver> default_constructor);
Node* InstanceOf(Node* object, Node* callable, Node* context);
@ -3153,6 +3162,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
void InitializeFunctionContext(Node* native_context, Node* context,
int slots);
TNode<JSArray> ArrayCreate(TNode<Context> context, TNode<Number> length);
private:
friend class CodeStubArguments;