@@ -233,15 +233,24 @@ RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
233233}
234234
235235
236- static Object* ArrayConstructorCommon (Isolate* isolate,
237- Handle<JSFunction> constructor,
238- Handle<JSFunction> new_target,
239- Handle<AllocationSite> site,
240- Arguments* caller_args) {
236+ namespace {
237+
238+ Object* ArrayConstructorCommon (Isolate* isolate, Handle<JSFunction> constructor,
239+ Handle<JSReceiver> new_target,
240+ Handle<AllocationSite> site,
241+ Arguments* caller_args) {
241242 Factory* factory = isolate->factory ();
242243
244+ // If called through new, new.target can be:
245+ // - a subclass of constructor,
246+ // - a proxy wrapper around constructor, or
247+ // - the constructor itself.
248+ // If called through Reflect.construct, it's guaranteed to be a constructor by
249+ // REFLECT_CONSTRUCT_PREPARE.
250+ DCHECK (new_target->IsConstructor ());
251+
243252 bool holey = false ;
244- bool can_use_type_feedback = true ;
253+ bool can_use_type_feedback = !site. is_null () ;
245254 bool can_inline_array_constructor = true ;
246255 if (caller_args->length () == 1 ) {
247256 Handle<Object> argument_one = caller_args->at <Object>(0 );
@@ -263,43 +272,42 @@ static Object* ArrayConstructorCommon(Isolate* isolate,
263272 }
264273 }
265274
266- Handle<JSArray> array;
267- if (!site.is_null () && can_use_type_feedback) {
268- ElementsKind to_kind = site->GetElementsKind ();
269- if (holey && !IsFastHoleyElementsKind (to_kind)) {
270- to_kind = GetHoleyElementsKind (to_kind);
271- // Update the allocation site info to reflect the advice alteration.
272- site->SetElementsKind (to_kind);
273- }
275+ // TODO(verwaest): new_target could be a proxy. Read new.target.prototype in
276+ // that case.
277+ Handle<JSFunction> original_function = Handle<JSFunction>::cast (new_target);
274278
275- // We should allocate with an initial map that reflects the allocation site
276- // advice. Therefore we use AllocateJSObjectFromMap instead of passing
277- // the constructor.
278- Handle<Map> initial_map (constructor->initial_map (), isolate);
279- if (to_kind != initial_map->elements_kind ()) {
280- initial_map = Map::AsElementsKind (initial_map, to_kind);
281- }
279+ JSFunction::EnsureHasInitialMap (constructor);
282280
283- // If we don't care to track arrays of to_kind ElementsKind, then
284- // don't emit a memento for them.
285- Handle<AllocationSite> allocation_site;
286- if (AllocationSite::GetMode (to_kind) == TRACK_ALLOCATION_SITE) {
287- allocation_site = site;
288- }
281+ // TODO(verwaest): original_function could have non-instance-prototype
282+ // (non-JSReceiver), requiring fallback to the intrinsicDefaultProto.
283+ Handle<Map> initial_map =
284+ JSFunction::EnsureDerivedHasInitialMap (original_function, constructor);
289285
290- array = Handle<JSArray>::cast (
291- factory->NewJSObjectFromMap (initial_map, NOT_TENURED, allocation_site));
292- } else {
293- array = Handle<JSArray>::cast (factory->NewJSObject (constructor));
286+ ElementsKind to_kind = can_use_type_feedback ? site->GetElementsKind ()
287+ : initial_map->elements_kind ();
288+ if (holey && !IsFastHoleyElementsKind (to_kind)) {
289+ to_kind = GetHoleyElementsKind (to_kind);
290+ // Update the allocation site info to reflect the advice alteration.
291+ if (!site.is_null ()) site->SetElementsKind (to_kind);
292+ }
294293
295- // We might need to transition to holey
296- ElementsKind kind = constructor->initial_map ()->elements_kind ();
297- if (holey && !IsFastHoleyElementsKind (kind)) {
298- kind = GetHoleyElementsKind (kind);
299- JSObject::TransitionElementsKind (array, kind);
300- }
294+ // We should allocate with an initial map that reflects the allocation site
295+ // advice. Therefore we use AllocateJSObjectFromMap instead of passing
296+ // the constructor.
297+ if (to_kind != initial_map->elements_kind ()) {
298+ initial_map = Map::AsElementsKind (initial_map, to_kind);
299+ }
300+
301+ // If we don't care to track arrays of to_kind ElementsKind, then
302+ // don't emit a memento for them.
303+ Handle<AllocationSite> allocation_site;
304+ if (AllocationSite::GetMode (to_kind) == TRACK_ALLOCATION_SITE) {
305+ allocation_site = site;
301306 }
302307
308+ Handle<JSArray> array = Handle<JSArray>::cast (
309+ factory->NewJSObjectFromMap (initial_map, NOT_TENURED, allocation_site));
310+
303311 factory->NewJSArrayStorage (array, 0 , 0 , DONT_INITIALIZE_ARRAY_ELEMENTS);
304312
305313 ElementsKind old_kind = array->GetElementsKind ();
@@ -314,21 +322,28 @@ static Object* ArrayConstructorCommon(Isolate* isolate,
314322 site->SetDoNotInlineCall ();
315323 }
316324
317- // Set up the prototoype using original function.
318- // TODO(dslomov): instead of setting the __proto__,
319- // use and cache the correct map.
320- if (*new_target != *constructor) {
321- if (new_target->has_instance_prototype ()) {
322- Handle<Object> prototype (new_target->instance_prototype (), isolate);
323- MAYBE_RETURN (JSObject::SetPrototype (array, prototype, false ,
324- Object::THROW_ON_ERROR),
325- isolate->heap ()->exception ());
326- }
327- }
328-
329325 return *array;
330326}
331327
328+ } // namespace
329+
330+
331+ RUNTIME_FUNCTION (Runtime_NewArray) {
332+ HandleScope scope (isolate);
333+ DCHECK_LE (3 , args.length ());
334+ int const argc = args.length () - 3 ;
335+ // TODO(bmeurer): Remove this Arguments nonsense.
336+ Arguments argv (argc, args.arguments () - 1 );
337+ CONVERT_ARG_HANDLE_CHECKED (JSFunction, constructor, 0 );
338+ CONVERT_ARG_HANDLE_CHECKED (JSReceiver, new_target, argc + 1 );
339+ CONVERT_ARG_HANDLE_CHECKED (HeapObject, type_info, argc + 2 );
340+ // TODO(bmeurer): Use MaybeHandle to pass around the AllocationSite.
341+ Handle<AllocationSite> site = type_info->IsAllocationSite ()
342+ ? Handle<AllocationSite>::cast (type_info)
343+ : Handle<AllocationSite>::null ();
344+ return ArrayConstructorCommon (isolate, constructor, new_target, site, &argv);
345+ }
346+
332347
333348RUNTIME_FUNCTION (Runtime_ArrayConstructor) {
334349 HandleScope scope (isolate);
@@ -364,25 +379,6 @@ RUNTIME_FUNCTION(Runtime_ArrayConstructor) {
364379}
365380
366381
367- RUNTIME_FUNCTION (Runtime_ArrayConstructorWithSubclassing) {
368- HandleScope scope (isolate);
369- int args_length = args.length ();
370- CHECK (args_length >= 2 );
371-
372- // This variables and checks work around -Werror=strict-overflow.
373- int pre_last_arg_index = args_length - 2 ;
374- int last_arg_index = args_length - 1 ;
375- CHECK (pre_last_arg_index >= 0 );
376- CHECK (last_arg_index >= 0 );
377-
378- CONVERT_ARG_HANDLE_CHECKED (JSFunction, constructor, pre_last_arg_index);
379- CONVERT_ARG_HANDLE_CHECKED (JSFunction, new_target, last_arg_index);
380- Arguments caller_args (args_length - 2 , args.arguments ());
381- return ArrayConstructorCommon (isolate, constructor, new_target,
382- Handle<AllocationSite>::null (), &caller_args);
383- }
384-
385-
386382RUNTIME_FUNCTION (Runtime_InternalArrayConstructor) {
387383 HandleScope scope (isolate);
388384 Arguments empty_args (0 , NULL );
0 commit comments