Commit 2851fede authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[Collections] Move Set constructor to CSA

Bug: v8:5717
Change-Id: Idf29fd079c0cdd6c2498b2ea5bfb54e0c0d52c56
Reviewed-on: https://chromium-review.googlesource.com/526433
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45769}
parent b66be9b8
......@@ -2963,10 +2963,25 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
factory->NewJSObject(isolate->object_function(), TENURED);
Handle<JSFunction> js_set_fun =
InstallFunction(global, "Set", JS_SET_TYPE, JSSet::kSize, prototype,
Builtins::kIllegal);
Builtins::kSetConstructor);
InstallWithIntrinsicDefaultProto(isolate, js_set_fun,
Context::JS_SET_FUN_INDEX);
Handle<SharedFunctionInfo> shared(js_set_fun->shared(), isolate);
shared->SetConstructStub(*isolate->builtins()->JSBuiltinsConstructStub());
shared->set_instance_class_name(isolate->heap()->Set_string());
shared->set_internal_formal_parameter_count(1);
shared->set_length(0);
// Install the "constructor" property on the {prototype}.
JSObject::AddProperty(prototype, factory->constructor_string(), js_set_fun,
DONT_ENUM);
// Install the @@toStringTag property on the {prototype}.
JSObject::AddProperty(
prototype, factory->to_string_tag_symbol(), factory->Set_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> set_has =
SimpleInstallFunction(prototype, "has", Builtins::kSetHas, 1, true);
InstallWithIntrinsicDefaultProto(isolate, set_has,
......
......@@ -18,13 +18,15 @@ class CollectionsBuiltinsAssembler : public CodeStubAssembler {
: CodeStubAssembler(state) {}
protected:
Node* AllocateJSMap(Node* js_map_function);
Node* AllocateJSCollection(Node* js_map_function);
Node* CallGetRaw(Node* const table, Node* const key);
template <typename CollectionType, int entrysize>
Node* CallHasRaw(Node* const table, Node* const key);
};
Node* CollectionsBuiltinsAssembler::AllocateJSMap(Node* js_map_function) {
Node* CollectionsBuiltinsAssembler::AllocateJSCollection(
Node* js_map_function) {
CSA_ASSERT(this, IsConstructorMap(LoadMap(js_map_function)));
Node* const initial_map = LoadObjectField(
js_map_function, JSFunction::kPrototypeOrInitialMapOffset);
Node* const instance = AllocateJSObjectFromMap(initial_map);
......@@ -57,7 +59,7 @@ TF_BUILTIN(MapConstructor, CollectionsBuiltinsAssembler) {
BIND(&if_targetisnotmodified);
{
Node* const instance = AllocateJSMap(js_map_fun);
Node* const instance = AllocateJSCollection(js_map_fun);
var_result.Bind(instance);
Goto(&init);
}
......@@ -137,7 +139,7 @@ TF_BUILTIN(MapConstructor, CollectionsBuiltinsAssembler) {
BIND(&if_notcallable);
{
Node* const message_id = SmiConstant(MessageTemplate::kPropertyNotFunction);
Node* const receiver_str = HeapConstant(isolate()->factory()->set_string());
Node* const receiver_str = HeapConstant(isolate()->factory()->add_string());
CallRuntime(Runtime::kThrowTypeError, context, message_id, adder,
receiver_str, var_result.value());
Unreachable();
......@@ -147,7 +149,111 @@ TF_BUILTIN(MapConstructor, CollectionsBuiltinsAssembler) {
{
Node* const message_id =
SmiConstant(MessageTemplate::kConstructorNotFunction);
CallRuntime(Runtime::kThrowTypeError, context, message_id, new_target);
CallRuntime(Runtime::kThrowTypeError, context, message_id,
HeapConstant(isolate()->factory()->Map_string()));
Unreachable();
}
BIND(&exit);
Return(var_result.value());
}
TF_BUILTIN(SetConstructor, CollectionsBuiltinsAssembler) {
// TODO(gsathya): Don't use arguments adaptor
Node* const iterable = Parameter(Descriptor::kIterable);
Node* const new_target = Parameter(Descriptor::kNewTarget);
Node* const context = Parameter(Descriptor::kContext);
Label if_target_is_undefined(this, Label::kDeferred);
GotoIf(IsUndefined(new_target), &if_target_is_undefined);
Node* const native_context = LoadNativeContext(context);
Node* const js_set_fun =
LoadContextElement(native_context, Context::JS_SET_FUN_INDEX);
VARIABLE(var_result, MachineRepresentation::kTagged);
Label init(this), exit(this), if_targetisnotmodified(this),
if_targetismodified(this);
Branch(WordEqual(js_set_fun, new_target), &if_targetisnotmodified,
&if_targetismodified);
BIND(&if_targetisnotmodified);
{
Node* const instance = AllocateJSCollection(js_set_fun);
var_result.Bind(instance);
Goto(&init);
}
BIND(&if_targetismodified);
{
ConstructorBuiltinsAssembler constructor_assembler(this->state());
Node* const instance = constructor_assembler.EmitFastNewObject(
context, js_set_fun, new_target);
var_result.Bind(instance);
Goto(&init);
}
BIND(&init);
// TODO(gsathya): Remove runtime call once OrderedHashTable is ported.
CallRuntime(Runtime::kSetInitialize, context, var_result.value());
GotoIf(Word32Or(IsUndefined(iterable), IsNull(iterable)), &exit);
Label if_notcallable(this);
// TODO(gsathya): Add fast path for unmodified maps.
Node* const adder = GetProperty(context, var_result.value(),
isolate()->factory()->add_string());
GotoIf(TaggedIsSmi(adder), &if_notcallable);
GotoIfNot(IsCallable(adder), &if_notcallable);
IteratorBuiltinsAssembler iterator_assembler(this->state());
Node* const iterator = iterator_assembler.GetIterator(context, iterable);
GotoIf(IsUndefined(iterator), &exit);
Node* const fast_iterator_result_map =
LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
VARIABLE(var_exception, MachineRepresentation::kTagged, UndefinedConstant());
Label loop(this), if_notobject(this), if_exception(this);
Goto(&loop);
BIND(&loop);
{
Node* const next = iterator_assembler.IteratorStep(
context, iterator, &exit, fast_iterator_result_map);
Node* const next_value = iterator_assembler.IteratorValue(
context, next, fast_iterator_result_map);
Node* add_call = CallJS(CodeFactory::Call(isolate()), context, adder,
var_result.value(), next_value);
GotoIfException(add_call, &if_exception, &var_exception);
Goto(&loop);
}
BIND(&if_exception);
{
iterator_assembler.IteratorClose(context, iterator, var_exception.value());
}
BIND(&if_notcallable);
{
Node* const message_id = SmiConstant(MessageTemplate::kPropertyNotFunction);
Node* const receiver_str = HeapConstant(isolate()->factory()->add_string());
CallRuntime(Runtime::kThrowTypeError, context, message_id, adder,
receiver_str, var_result.value());
Unreachable();
}
BIND(&if_target_is_undefined);
{
Node* const message_id =
SmiConstant(MessageTemplate::kConstructorNotFunction);
CallRuntime(Runtime::kThrowTypeError, context, message_id,
HeapConstant(isolate()->factory()->Set_string()));
Unreachable();
}
......
......@@ -849,6 +849,7 @@ namespace internal {
TFJ(RegExpPrototypeSplit, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
\
/* Set */ \
TFJ(SetConstructor, 1, kIterable) \
TFJ(SetHas, 1, kKey) \
\
/* SharedArrayBuffer */ \
......@@ -1062,6 +1063,8 @@ namespace internal {
CPP(StringPrototypeNormalize)
#endif // V8_INTL_SUPPORT
// The exception thrown in the following builtins are caught
// internally and result in a promise rejection.
#define BUILTIN_PROMISE_REJECTION_PREDICTION_LIST(V) \
V(AsyncFromSyncIteratorPrototypeNext) \
V(AsyncFromSyncIteratorPrototypeReturn) \
......@@ -1080,10 +1083,15 @@ namespace internal {
V(ResolveNativePromise) \
V(ResolvePromise)
// The exception thrown in the following builtins are caught
// internally and should not trigger the catch prediction heuristic.
#define BUILTIN_EXCEPTION_CAUGHT_PREDICTION_LIST(V) V(PromiseHandleReject)
// The exception thrown in the following builtins are not caught
// internally and should trigger the catch prediction heuristic.
#define BUILTIN_EXCEPTION_UNCAUGHT_PREDICTION_LIST(V) \
V(MapConstructor) \
V(SetConstructor) \
V(GeneratorPrototypeNext) \
V(GeneratorPrototypeReturn) \
V(GeneratorPrototypeThrow)
......
......@@ -314,6 +314,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(GenericHash) \
V(MapIteratorInitialize) \
V(MapInitialize) \
V(SetInitialize) \
/* Called from builtins */ \
V(StringParseFloat) \
V(StringParseInt) \
......@@ -583,6 +584,8 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) {
case Builtins::kNumberPrototypeToPrecision:
case Builtins::kNumberPrototypeToString:
case Builtins::kNumberPrototypeValueOf:
// Set builtins.
case Builtins::kSetConstructor:
// String builtins. Strings are immutable.
case Builtins::kStringFromCharCode:
case Builtins::kStringFromCodePoint:
......
......@@ -8,6 +8,7 @@
#define INTERNALIZED_STRING_LIST(V) \
V(anonymous_function_string, "(anonymous function)") \
V(anonymous_string, "anonymous") \
V(add_string, "add") \
V(apply_string, "apply") \
V(arguments_string, "arguments") \
V(Arguments_string, "Arguments") \
......
......@@ -119,26 +119,6 @@ function GetHash(key) {
// -------------------------------------------------------------------
// Harmony Set
function SetConstructor(iterable) {
if (IS_UNDEFINED(new.target)) {
throw %make_type_error(kConstructorNotFunction, "Set");
}
%_SetInitialize(this);
if (!IS_NULL_OR_UNDEFINED(iterable)) {
var adder = this.add;
if (!IS_CALLABLE(adder)) {
throw %make_type_error(kPropertyNotFunction, adder, 'add', this);
}
for (var value of iterable) {
%_Call(adder, this, value);
}
}
}
function SetAdd(key) {
if (!IS_SET(this)) {
throw %make_type_error(kIncompatibleMethodReceiver, 'Set.prototype.add', this);
......@@ -240,12 +220,6 @@ function SetForEach(f, receiver) {
// -------------------------------------------------------------------
%SetCode(GlobalSet, SetConstructor);
%FunctionSetLength(GlobalSet, 0);
%AddNamedProperty(GlobalSet.prototype, "constructor", GlobalSet, DONT_ENUM);
%AddNamedProperty(GlobalSet.prototype, toStringTagSymbol, "Set",
DONT_ENUM | READ_ONLY);
%FunctionSetLength(SetForEach, 1);
// Set up the non-enumerable functions on the Set prototype object.
......
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