[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:
parent
f289f1cafb
commit
bada4d5ccc
@ -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,
|
||||
|
@ -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 =
|
||||
|
@ -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>(
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user