Commit bada4d5c authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[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/1296487Reviewed-by: 's avatarMathias Bynens <mathias@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56928}
parent f289f1ca
This diff is collapsed.
......@@ -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,11 +73,11 @@ class TypedArrayBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
JSTypedArray::kBufferOffset);
}
TNode<Object> GetDefaultConstructor(TNode<Context> context,
TNode<JSTypedArray> exemplar);
TNode<JSFunction> GetDefaultConstructor(TNode<Context> context,
TNode<JSTypedArray> exemplar);
TNode<Object> TypedArraySpeciesConstructor(TNode<Context> context,
TNode<JSTypedArray> exemplar);
TNode<JSReceiver> TypedArraySpeciesConstructor(TNode<Context> context,
TNode<JSTypedArray> exemplar);
TNode<JSTypedArray> SpeciesCreateByArrayBuffer(TNode<Context> context,
TNode<JSTypedArray> exemplar,
......
......@@ -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<Object> o,
TNode<Number> len) {
Node* constructor =
CallRuntime(Runtime::kArraySpeciesConstructor, context, o);
return ConstructJS(CodeFactory::Construct(isolate()), context, constructor,
len);
TNode<JSReceiver> CodeStubAssembler::ArraySpeciesCreate(TNode<Context> context,
TNode<Object> o,
TNode<Number> len) {
TNode<JSReceiver> constructor =
CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o));
return Construct(context, constructor, len);
}
Node* 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<JSReceiver> CodeStubAssembler::InternalArrayCreate(TNode<Context> context,
TNode<Number> 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<Number> len);
Node* InternalArrayCreate(TNode<Context> context, TNode<Number> len);
TNode<JSReceiver> ArraySpeciesCreate(TNode<Context> context,
TNode<Object> originalArray,
TNode<Number> len);
TNode<JSReceiver> 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;
......
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