LCOV - code coverage report
Current view: top level - src/builtins - builtins-constructor-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 334 338 98.8 %
Date: 2017-10-20 Functions: 45 47 95.7 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/builtins/builtins-constructor-gen.h"
       6             : 
       7             : #include "src/ast/ast.h"
       8             : #include "src/builtins/builtins-call-gen.h"
       9             : #include "src/builtins/builtins-constructor.h"
      10             : #include "src/builtins/builtins-utils-gen.h"
      11             : #include "src/builtins/builtins.h"
      12             : #include "src/code-factory.h"
      13             : #include "src/code-stub-assembler.h"
      14             : #include "src/counters.h"
      15             : #include "src/interface-descriptors.h"
      16             : #include "src/objects-inl.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : 
      21          31 : void Builtins::Generate_ConstructVarargs(MacroAssembler* masm) {
      22             :   Generate_CallOrConstructVarargs(masm,
      23          31 :                                   BUILTIN_CODE(masm->isolate(), Construct));
      24          31 : }
      25             : 
      26          31 : void Builtins::Generate_ConstructForwardVarargs(MacroAssembler* masm) {
      27             :   Generate_CallOrConstructForwardVarargs(
      28             :       masm, CallOrConstructMode::kConstruct,
      29          31 :       BUILTIN_CODE(masm->isolate(), Construct));
      30          31 : }
      31             : 
      32          31 : void Builtins::Generate_ConstructFunctionForwardVarargs(MacroAssembler* masm) {
      33             :   Generate_CallOrConstructForwardVarargs(
      34             :       masm, CallOrConstructMode::kConstruct,
      35          31 :       BUILTIN_CODE(masm->isolate(), ConstructFunction));
      36          31 : }
      37             : 
      38         124 : TF_BUILTIN(ConstructWithArrayLike, CallOrConstructBuiltinsAssembler) {
      39             :   Node* target = Parameter(ConstructWithArrayLikeDescriptor::kTarget);
      40             :   Node* new_target = Parameter(ConstructWithArrayLikeDescriptor::kNewTarget);
      41             :   Node* arguments_list =
      42             :       Parameter(ConstructWithArrayLikeDescriptor::kArgumentsList);
      43             :   Node* context = Parameter(ConstructWithArrayLikeDescriptor::kContext);
      44          31 :   CallOrConstructWithArrayLike(target, new_target, arguments_list, context);
      45          31 : }
      46             : 
      47         124 : TF_BUILTIN(ConstructWithSpread, CallOrConstructBuiltinsAssembler) {
      48             :   Node* target = Parameter(ConstructWithSpreadDescriptor::kTarget);
      49             :   Node* new_target = Parameter(ConstructWithSpreadDescriptor::kNewTarget);
      50             :   Node* spread = Parameter(ConstructWithSpreadDescriptor::kSpread);
      51             :   Node* args_count = Parameter(ConstructWithSpreadDescriptor::kArgumentsCount);
      52             :   Node* context = Parameter(ConstructWithSpreadDescriptor::kContext);
      53          31 :   CallOrConstructWithSpread(target, new_target, spread, args_count, context);
      54          31 : }
      55             : 
      56             : typedef compiler::Node Node;
      57             : 
      58         124 : Node* ConstructorBuiltinsAssembler::EmitFastNewClosure(Node* shared_info,
      59             :                                                        Node* feedback_vector,
      60             :                                                        Node* slot,
      61             :                                                        Node* context) {
      62         124 :   Isolate* isolate = this->isolate();
      63             :   Factory* factory = isolate->factory();
      64         124 :   IncrementCounter(isolate->counters()->fast_new_closure_total(), 1);
      65             : 
      66             :   Node* compiler_hints =
      67             :       LoadObjectField(shared_info, SharedFunctionInfo::kCompilerHintsOffset,
      68         124 :                       MachineType::Uint32());
      69             : 
      70             :   // The calculation of |function_map_index| must be in sync with
      71             :   // SharedFunctionInfo::function_map_index().
      72             :   Node* function_map_index =
      73             :       IntPtrAdd(DecodeWordFromWord32<SharedFunctionInfo::FunctionMapIndexBits>(
      74             :                     compiler_hints),
      75         496 :                 IntPtrConstant(Context::FIRST_FUNCTION_MAP_INDEX));
      76             :   CSA_ASSERT(this, UintPtrLessThanOrEqual(
      77             :                        function_map_index,
      78             :                        IntPtrConstant(Context::LAST_FUNCTION_MAP_INDEX)));
      79             : 
      80             :   // Get the function map in the current native context and set that
      81             :   // as the map of the allocated object.
      82         248 :   Node* native_context = LoadNativeContext(context);
      83         248 :   Node* function_map = LoadContextElement(native_context, function_map_index);
      84             : 
      85             :   // Create a new closure from the given function info in new space
      86             :   Node* instance_size_in_bytes =
      87         248 :       TimesPointerSize(LoadMapInstanceSize(function_map));
      88         124 :   Node* result = Allocate(instance_size_in_bytes);
      89         124 :   StoreMapNoWriteBarrier(result, function_map);
      90             :   InitializeJSObjectBody(result, function_map, instance_size_in_bytes,
      91         124 :                          JSFunction::kSizeWithoutPrototype);
      92             : 
      93             :   // Initialize the rest of the function.
      94             :   Node* empty_fixed_array = HeapConstant(factory->empty_fixed_array());
      95             :   StoreObjectFieldNoWriteBarrier(result, JSObject::kPropertiesOrHashOffset,
      96         124 :                                  empty_fixed_array);
      97             :   StoreObjectFieldNoWriteBarrier(result, JSObject::kElementsOffset,
      98         124 :                                  empty_fixed_array);
      99             :   {
     100             :     // Set function prototype if necessary.
     101         124 :     Label done(this), init_prototype(this);
     102             :     Branch(IsFunctionWithPrototypeSlotMap(function_map), &init_prototype,
     103         248 :            &done);
     104             : 
     105         124 :     BIND(&init_prototype);
     106             :     StoreObjectFieldNoWriteBarrier(
     107         248 :         result, JSFunction::kPrototypeOrInitialMapOffset, TheHoleConstant());
     108         124 :     Goto(&done);
     109             : 
     110         248 :     BIND(&done);
     111             :   }
     112             : 
     113             :   Node* literals_cell = LoadFeedbackVectorSlot(
     114         124 :       feedback_vector, slot, 0, CodeStubAssembler::SMI_PARAMETERS);
     115             :   {
     116             :     // Bump the closure counter encoded in the cell's map.
     117         248 :     Node* cell_map = LoadMap(literals_cell);
     118         124 :     Label no_closures(this), one_closure(this), cell_done(this);
     119             : 
     120         248 :     GotoIf(IsNoClosuresCellMap(cell_map), &no_closures);
     121         248 :     GotoIf(IsOneClosureCellMap(cell_map), &one_closure);
     122             :     CSA_ASSERT(this, IsManyClosuresCellMap(cell_map), cell_map, literals_cell,
     123             :                feedback_vector, slot);
     124         124 :     Goto(&cell_done);
     125             : 
     126         124 :     BIND(&no_closures);
     127         124 :     StoreMapNoWriteBarrier(literals_cell, Heap::kOneClosureCellMapRootIndex);
     128         124 :     Goto(&cell_done);
     129             : 
     130         124 :     BIND(&one_closure);
     131         124 :     StoreMapNoWriteBarrier(literals_cell, Heap::kManyClosuresCellMapRootIndex);
     132         124 :     Goto(&cell_done);
     133             : 
     134         248 :     BIND(&cell_done);
     135             :   }
     136             :   StoreObjectFieldNoWriteBarrier(result, JSFunction::kFeedbackVectorOffset,
     137         124 :                                  literals_cell);
     138             :   StoreObjectFieldNoWriteBarrier(result, JSFunction::kSharedFunctionInfoOffset,
     139         124 :                                  shared_info);
     140         124 :   StoreObjectFieldNoWriteBarrier(result, JSFunction::kContextOffset, context);
     141             :   Handle<Code> lazy_builtin_handle(
     142             :       isolate->builtins()->builtin(Builtins::kCompileLazy));
     143             :   Node* lazy_builtin = HeapConstant(lazy_builtin_handle);
     144         124 :   StoreObjectFieldNoWriteBarrier(result, JSFunction::kCodeOffset, lazy_builtin);
     145         124 :   return result;
     146             : }
     147             : 
     148           0 : Node* ConstructorBuiltinsAssembler::NotHasBoilerplate(Node* literal_site) {
     149         744 :   return TaggedIsSmi(literal_site);
     150             : }
     151             : 
     152           0 : Node* ConstructorBuiltinsAssembler::LoadAllocationSiteBoilerplate(Node* site) {
     153             :   CSA_ASSERT(this, IsAllocationSite(site));
     154             :   return LoadObjectField(site,
     155           0 :                          AllocationSite::kTransitionInfoOrBoilerplateOffset);
     156             : }
     157             : 
     158         124 : TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) {
     159             :   Node* shared = Parameter(FastNewClosureDescriptor::kSharedFunctionInfo);
     160             :   Node* context = Parameter(FastNewClosureDescriptor::kContext);
     161             :   Node* vector = Parameter(FastNewClosureDescriptor::kVector);
     162             :   Node* slot = Parameter(FastNewClosureDescriptor::kSlot);
     163          62 :   Return(EmitFastNewClosure(shared, vector, slot, context));
     164          31 : }
     165             : 
     166         124 : TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) {
     167             :   Node* context = Parameter(Descriptor::kContext);
     168             :   Node* target = Parameter(Descriptor::kTarget);
     169             :   Node* new_target = Parameter(Descriptor::kNewTarget);
     170             : 
     171             :   Label call_runtime(this);
     172             : 
     173          31 :   Node* result = EmitFastNewObject(context, target, new_target, &call_runtime);
     174          31 :   Return(result);
     175             : 
     176          31 :   BIND(&call_runtime);
     177          31 :   TailCallRuntime(Runtime::kNewObject, context, target, new_target);
     178          31 : }
     179             : 
     180         217 : Node* ConstructorBuiltinsAssembler::EmitFastNewObject(Node* context,
     181             :                                                       Node* target,
     182             :                                                       Node* new_target) {
     183         217 :   VARIABLE(var_obj, MachineRepresentation::kTagged);
     184         217 :   Label call_runtime(this), end(this);
     185             : 
     186         217 :   Node* result = EmitFastNewObject(context, target, new_target, &call_runtime);
     187         217 :   var_obj.Bind(result);
     188         217 :   Goto(&end);
     189             : 
     190         217 :   BIND(&call_runtime);
     191         217 :   var_obj.Bind(CallRuntime(Runtime::kNewObject, context, target, new_target));
     192         217 :   Goto(&end);
     193             : 
     194         217 :   BIND(&end);
     195         434 :   return var_obj.value();
     196             : }
     197             : 
     198         248 : Node* ConstructorBuiltinsAssembler::EmitFastNewObject(Node* context,
     199             :                                                       Node* target,
     200             :                                                       Node* new_target,
     201             :                                                       Label* call_runtime) {
     202             :   CSA_ASSERT(this, HasInstanceType(target, JS_FUNCTION_TYPE));
     203             :   CSA_ASSERT(this, IsJSReceiver(new_target));
     204             : 
     205             :   // Verify that the new target is a JSFunction.
     206         496 :   Label fast(this), end(this);
     207         496 :   GotoIf(HasInstanceType(new_target, JS_FUNCTION_TYPE), &fast);
     208         248 :   Goto(call_runtime);
     209             : 
     210         248 :   BIND(&fast);
     211             : 
     212             :   // Load the initial map and verify that it's in fact a map.
     213             :   Node* initial_map =
     214             :       LoadObjectField(new_target, JSFunction::kPrototypeOrInitialMapOffset);
     215         496 :   GotoIf(TaggedIsSmi(initial_map), call_runtime);
     216         496 :   GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), call_runtime);
     217             : 
     218             :   // Fall back to runtime if the target differs from the new target's
     219             :   // initial map constructor.
     220             :   Node* new_target_constructor =
     221             :       LoadObjectField(initial_map, Map::kConstructorOrBackPointerOffset);
     222         496 :   GotoIf(WordNotEqual(target, new_target_constructor), call_runtime);
     223             : 
     224         496 :   VARIABLE(properties, MachineRepresentation::kTagged);
     225             : 
     226         248 :   Label instantiate_map(this), allocate_properties(this);
     227         496 :   GotoIf(IsDictionaryMap(initial_map), &allocate_properties);
     228             :   {
     229         496 :     properties.Bind(EmptyFixedArrayConstant());
     230         248 :     Goto(&instantiate_map);
     231             :   }
     232         248 :   BIND(&allocate_properties);
     233             :   {
     234         248 :     properties.Bind(AllocateNameDictionary(NameDictionary::kInitialCapacity));
     235         248 :     Goto(&instantiate_map);
     236             :   }
     237             : 
     238         248 :   BIND(&instantiate_map);
     239             : 
     240         248 :   Node* object = AllocateJSObjectFromMap(initial_map, properties.value());
     241             : 
     242             :   // Perform in-object slack tracking if requested.
     243         248 :   HandleSlackTracking(context, object, initial_map, JSObject::kHeaderSize);
     244         248 :   return object;
     245             : }
     246             : 
     247         248 : Node* ConstructorBuiltinsAssembler::EmitFastNewFunctionContext(
     248             :     Node* function, Node* slots, Node* context, ScopeType scope_type) {
     249         496 :   slots = ChangeUint32ToWord(slots);
     250             : 
     251             :   // TODO(ishell): Use CSA::OptimalParameterMode() here.
     252             :   ParameterMode mode = INTPTR_PARAMETERS;
     253         496 :   Node* min_context_slots = IntPtrConstant(Context::MIN_CONTEXT_SLOTS);
     254         496 :   Node* length = IntPtrAdd(slots, min_context_slots);
     255         248 :   Node* size = GetFixedArrayAllocationSize(length, PACKED_ELEMENTS, mode);
     256             : 
     257             :   // Create a new closure from the given function info in new space
     258         248 :   Node* function_context = AllocateInNewSpace(size);
     259             : 
     260             :   Heap::RootListIndex context_type;
     261         248 :   switch (scope_type) {
     262             :     case EVAL_SCOPE:
     263             :       context_type = Heap::kEvalContextMapRootIndex;
     264             :       break;
     265             :     case FUNCTION_SCOPE:
     266             :       context_type = Heap::kFunctionContextMapRootIndex;
     267         124 :       break;
     268             :     default:
     269           0 :       UNREACHABLE();
     270             :   }
     271         248 :   StoreMapNoWriteBarrier(function_context, context_type);
     272             :   StoreObjectFieldNoWriteBarrier(function_context, Context::kLengthOffset,
     273         496 :                                  SmiTag(length));
     274             : 
     275             :   // Set up the fixed slots.
     276             :   StoreFixedArrayElement(function_context, Context::CLOSURE_INDEX, function,
     277         248 :                          SKIP_WRITE_BARRIER);
     278             :   StoreFixedArrayElement(function_context, Context::PREVIOUS_INDEX, context,
     279         248 :                          SKIP_WRITE_BARRIER);
     280             :   StoreFixedArrayElement(function_context, Context::EXTENSION_INDEX,
     281         496 :                          TheHoleConstant(), SKIP_WRITE_BARRIER);
     282             : 
     283             :   // Copy the native context from the previous context.
     284         496 :   Node* native_context = LoadNativeContext(context);
     285             :   StoreFixedArrayElement(function_context, Context::NATIVE_CONTEXT_INDEX,
     286         248 :                          native_context, SKIP_WRITE_BARRIER);
     287             : 
     288             :   // Initialize the rest of the slots to undefined.
     289         496 :   Node* undefined = UndefinedConstant();
     290             :   BuildFastFixedArrayForEach(
     291             :       function_context, PACKED_ELEMENTS, min_context_slots, length,
     292             :       [this, undefined](Node* context, Node* offset) {
     293             :         StoreNoWriteBarrier(MachineRepresentation::kTagged, context, offset,
     294         248 :                             undefined);
     295             :       },
     296         496 :       mode);
     297             : 
     298         248 :   return function_context;
     299             : }
     300             : 
     301         124 : TF_BUILTIN(FastNewFunctionContextEval, ConstructorBuiltinsAssembler) {
     302             :   Node* function = Parameter(FastNewFunctionContextDescriptor::kFunction);
     303             :   Node* slots = Parameter(FastNewFunctionContextDescriptor::kSlots);
     304             :   Node* context = Parameter(FastNewFunctionContextDescriptor::kContext);
     305             :   Return(EmitFastNewFunctionContext(function, slots, context,
     306          62 :                                     ScopeType::EVAL_SCOPE));
     307          31 : }
     308             : 
     309         124 : TF_BUILTIN(FastNewFunctionContextFunction, ConstructorBuiltinsAssembler) {
     310             :   Node* function = Parameter(FastNewFunctionContextDescriptor::kFunction);
     311             :   Node* slots = Parameter(FastNewFunctionContextDescriptor::kSlots);
     312             :   Node* context = Parameter(FastNewFunctionContextDescriptor::kContext);
     313             :   Return(EmitFastNewFunctionContext(function, slots, context,
     314          62 :                                     ScopeType::FUNCTION_SCOPE));
     315          31 : }
     316             : 
     317         124 : Node* ConstructorBuiltinsAssembler::EmitCreateRegExpLiteral(
     318             :     Node* feedback_vector, Node* slot, Node* pattern, Node* flags,
     319             :     Node* context) {
     320         248 :   Label call_runtime(this, Label::kDeferred), end(this);
     321             : 
     322         248 :   VARIABLE(result, MachineRepresentation::kTagged);
     323             :   Node* literal_site =
     324         124 :       LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS);
     325         124 :   GotoIf(NotHasBoilerplate(literal_site), &call_runtime);
     326             :   {
     327             :     Node* boilerplate = literal_site;
     328             :     CSA_ASSERT(this, IsJSRegExp(boilerplate));
     329             :     int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
     330         124 :     Node* copy = Allocate(size);
     331         992 :     for (int offset = 0; offset < size; offset += kPointerSize) {
     332             :       Node* value = LoadObjectField(boilerplate, offset);
     333         868 :       StoreObjectFieldNoWriteBarrier(copy, offset, value);
     334             :     }
     335         124 :     result.Bind(copy);
     336         124 :     Goto(&end);
     337             :   }
     338             : 
     339         124 :   BIND(&call_runtime);
     340             :   {
     341             :     result.Bind(CallRuntime(Runtime::kCreateRegExpLiteral, context,
     342         248 :                             feedback_vector, SmiTag(slot), pattern, flags));
     343         124 :     Goto(&end);
     344             :   }
     345             : 
     346         124 :   BIND(&end);
     347         248 :   return result.value();
     348             : }
     349             : 
     350         155 : TF_BUILTIN(CreateRegExpLiteral, ConstructorBuiltinsAssembler) {
     351             :   Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
     352          62 :   Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
     353             :   Node* pattern = Parameter(Descriptor::kPattern);
     354             :   Node* flags = Parameter(Descriptor::kFlags);
     355             :   Node* context = Parameter(Descriptor::kContext);
     356             :   Node* result =
     357          31 :       EmitCreateRegExpLiteral(feedback_vector, slot, pattern, flags, context);
     358          31 :   Return(result);
     359          31 : }
     360             : 
     361         124 : Node* ConstructorBuiltinsAssembler::EmitCreateShallowArrayLiteral(
     362             :     Node* feedback_vector, Node* slot, Node* context, Label* call_runtime,
     363             :     AllocationSiteMode allocation_site_mode) {
     364         248 :   Label zero_capacity(this), cow_elements(this), fast_elements(this),
     365         124 :       return_result(this);
     366         248 :   VARIABLE(result, MachineRepresentation::kTagged);
     367             : 
     368             :   Node* allocation_site =
     369         124 :       LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS);
     370         124 :   GotoIf(NotHasBoilerplate(allocation_site), call_runtime);
     371             : 
     372             :   Node* boilerplate = LoadAllocationSiteBoilerplate(allocation_site);
     373             :   allocation_site =
     374         124 :       allocation_site_mode == TRACK_ALLOCATION_SITE ? allocation_site : nullptr;
     375             : 
     376             :   CSA_ASSERT(this, IsJSArrayMap(LoadMap(boilerplate)));
     377             :   ParameterMode mode = OptimalParameterMode();
     378         248 :   return CloneFastJSArray(context, boilerplate, mode, allocation_site);
     379             : }
     380             : 
     381         155 : TF_BUILTIN(CreateShallowArrayLiteral, ConstructorBuiltinsAssembler) {
     382             :   Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
     383          62 :   Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
     384             :   Node* constant_elements = Parameter(Descriptor::kConstantElements);
     385             :   Node* context = Parameter(Descriptor::kContext);
     386             :   Label call_runtime(this, Label::kDeferred);
     387             :   Return(EmitCreateShallowArrayLiteral(feedback_vector, slot, context,
     388             :                                        &call_runtime,
     389          62 :                                        DONT_TRACK_ALLOCATION_SITE));
     390             : 
     391          31 :   BIND(&call_runtime);
     392             :   {
     393          31 :     Comment("call runtime");
     394             :     int const flags =
     395             :         AggregateLiteral::kDisableMementos | AggregateLiteral::kIsShallow;
     396             :     Return(CallRuntime(Runtime::kCreateArrayLiteral, context, feedback_vector,
     397          93 :                        SmiTag(slot), constant_elements, SmiConstant(flags)));
     398          31 :   }
     399          31 : }
     400             : 
     401         124 : Node* ConstructorBuiltinsAssembler::EmitCreateEmptyArrayLiteral(
     402             :     Node* feedback_vector, Node* slot, Node* context) {
     403             :   // Array literals always have a valid AllocationSite to properly track
     404             :   // elements transitions.
     405         124 :   VARIABLE(allocation_site, MachineRepresentation::kTagged,
     406             :            LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
     407             : 
     408         124 :   Label create_empty_array(this),
     409         124 :       initialize_allocation_site(this, Label::kDeferred), done(this);
     410         248 :   Branch(TaggedIsSmi(allocation_site.value()), &initialize_allocation_site,
     411         248 :          &create_empty_array);
     412             : 
     413             :   // TODO(cbruni): create the AllocationSite in CSA.
     414         124 :   BIND(&initialize_allocation_site);
     415             :   {
     416             :     allocation_site.Bind(
     417         248 :         CreateAllocationSiteInFeedbackVector(feedback_vector, SmiTag(slot)));
     418         124 :     Goto(&create_empty_array);
     419             :   }
     420             : 
     421         124 :   BIND(&create_empty_array);
     422             :   CSA_ASSERT(this, IsAllocationSite(allocation_site.value()));
     423         124 :   Node* kind = SmiToWord32(CAST(
     424             :       LoadObjectField(allocation_site.value(),
     425         248 :                       AllocationSite::kTransitionInfoOrBoilerplateOffset)));
     426             :   CSA_ASSERT(this, IsFastElementsKind(kind));
     427         248 :   Node* native_context = LoadNativeContext(context);
     428         124 :   Comment("LoadJSArrayElementsMap");
     429         248 :   Node* array_map = LoadJSArrayElementsMap(kind, native_context);
     430         248 :   Node* zero = SmiConstant(0);
     431         124 :   Comment("Allocate JSArray");
     432             :   Node* result =
     433             :       AllocateJSArray(GetInitialFastElementsKind(), array_map, zero, zero,
     434         124 :                       allocation_site.value(), ParameterMode::SMI_PARAMETERS);
     435             : 
     436         124 :   Goto(&done);
     437         124 :   BIND(&done);
     438             : 
     439         124 :   return result;
     440             : }
     441             : 
     442         155 : TF_BUILTIN(CreateEmptyArrayLiteral, ConstructorBuiltinsAssembler) {
     443             :   Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
     444          62 :   Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
     445             :   Node* context = Parameter(Descriptor::kContext);
     446          31 :   Node* result = EmitCreateEmptyArrayLiteral(feedback_vector, slot, context);
     447          31 :   Return(result);
     448          31 : }
     449             : 
     450         124 : Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral(
     451             :     Node* feedback_vector, Node* slot, Label* call_runtime) {
     452             :   Node* allocation_site =
     453         124 :       LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS);
     454         124 :   GotoIf(NotHasBoilerplate(allocation_site), call_runtime);
     455             : 
     456             :   Node* boilerplate = LoadAllocationSiteBoilerplate(allocation_site);
     457         248 :   Node* boilerplate_map = LoadMap(boilerplate);
     458             :   CSA_ASSERT(this, IsJSObjectMap(boilerplate_map));
     459             : 
     460         124 :   VARIABLE(var_properties, MachineRepresentation::kTagged);
     461             :   {
     462         248 :     Node* bit_field_3 = LoadMapBitField3(boilerplate_map);
     463         124 :     GotoIf(IsSetWord32<Map::Deprecated>(bit_field_3), call_runtime);
     464             :     // Directly copy over the property store for dict-mode boilerplates.
     465         124 :     Label if_dictionary(this), if_fast(this), done(this);
     466             :     Branch(IsSetWord32<Map::DictionaryMap>(bit_field_3), &if_dictionary,
     467         124 :            &if_fast);
     468         124 :     BIND(&if_dictionary);
     469             :     {
     470         124 :       Comment("Copy dictionary properties");
     471             :       var_properties.Bind(
     472         248 :           CopyNameDictionary(LoadSlowProperties(boilerplate), call_runtime));
     473             :       // Slow objects have no in-object properties.
     474         124 :       Goto(&done);
     475             :     }
     476         124 :     BIND(&if_fast);
     477             :     {
     478             :       // TODO(cbruni): support copying out-of-object properties.
     479         248 :       Node* boilerplate_properties = LoadFastProperties(boilerplate);
     480         248 :       GotoIfNot(IsEmptyFixedArray(boilerplate_properties), call_runtime);
     481         248 :       var_properties.Bind(EmptyFixedArrayConstant());
     482         124 :       Goto(&done);
     483             :     }
     484         248 :     BIND(&done);
     485             :   }
     486             : 
     487         248 :   VARIABLE(var_elements, MachineRepresentation::kTagged);
     488             :   {
     489             :     // Copy the elements backing store, assuming that it's flat.
     490         124 :     Label if_empty_fixed_array(this), if_copy_elements(this), done(this);
     491         248 :     Node* boilerplate_elements = LoadElements(boilerplate);
     492         124 :     Branch(IsEmptyFixedArray(boilerplate_elements), &if_empty_fixed_array,
     493         248 :            &if_copy_elements);
     494             : 
     495         124 :     BIND(&if_empty_fixed_array);
     496         124 :     var_elements.Bind(boilerplate_elements);
     497         124 :     Goto(&done);
     498             : 
     499         124 :     BIND(&if_copy_elements);
     500             :     CSA_ASSERT(this, Word32BinaryNot(
     501             :                          IsFixedCOWArrayMap(LoadMap(boilerplate_elements))));
     502             :     ExtractFixedArrayFlags flags;
     503             :     flags |= ExtractFixedArrayFlag::kAllFixedArrays;
     504             :     flags |= ExtractFixedArrayFlag::kNewSpaceAllocationOnly;
     505             :     flags |= ExtractFixedArrayFlag::kDontCopyCOW;
     506         124 :     var_elements.Bind(CloneFixedArray(boilerplate_elements, flags));
     507         124 :     Goto(&done);
     508         248 :     BIND(&done);
     509             :   }
     510             : 
     511             :   // Ensure new-space allocation for a fresh JSObject so we can skip write
     512             :   // barriers when copying all object fields.
     513             :   STATIC_ASSERT(JSObject::kMaxInstanceSize < kMaxRegularHeapObjectSize);
     514         248 :   Node* instance_size = TimesPointerSize(LoadMapInstanceSize(boilerplate_map));
     515             :   Node* allocation_size = instance_size;
     516         124 :   bool needs_allocation_memento = FLAG_allocation_site_pretenuring;
     517         124 :   if (needs_allocation_memento) {
     518             :     // Prepare for inner-allocating the AllocationMemento.
     519         248 :     allocation_size =
     520         248 :         IntPtrAdd(instance_size, IntPtrConstant(AllocationMemento::kSize));
     521             :   }
     522             : 
     523         124 :   Node* copy = AllocateInNewSpace(allocation_size);
     524             :   {
     525         124 :     Comment("Initialize Literal Copy");
     526             :     // Initialize Object fields.
     527         124 :     StoreMapNoWriteBarrier(copy, boilerplate_map);
     528             :     StoreObjectFieldNoWriteBarrier(copy, JSObject::kPropertiesOrHashOffset,
     529         124 :                                    var_properties.value());
     530             :     StoreObjectFieldNoWriteBarrier(copy, JSObject::kElementsOffset,
     531         124 :                                    var_elements.value());
     532             :   }
     533             : 
     534             :   // Initialize the AllocationMemento before potential GCs due to heap number
     535             :   // allocation when copying the in-object properties.
     536         124 :   if (needs_allocation_memento) {
     537         124 :     InitializeAllocationMemento(copy, instance_size, allocation_site);
     538             :   }
     539             : 
     540             :   {
     541             :     // Copy over in-object properties.
     542             :     Label continue_with_write_barrier(this), done_init(this);
     543         248 :     VARIABLE(offset, MachineType::PointerRepresentation(),
     544             :              IntPtrConstant(JSObject::kHeaderSize));
     545             :     // Mutable heap numbers only occur on 32-bit platforms.
     546             :     bool may_use_mutable_heap_numbers =
     547             :         FLAG_track_double_fields && !FLAG_unbox_double_fields;
     548             :     {
     549         124 :       Comment("Copy in-object properties fast");
     550             :       Label continue_fast(this, &offset);
     551         248 :       Branch(WordEqual(offset.value(), instance_size), &done_init,
     552         248 :              &continue_fast);
     553         124 :       BIND(&continue_fast);
     554         124 :       Node* field = LoadObjectField(boilerplate, offset.value());
     555             :       if (may_use_mutable_heap_numbers) {
     556             :         Label store_field(this);
     557             :         GotoIf(TaggedIsSmi(field), &store_field);
     558             :         GotoIf(IsMutableHeapNumber(field), &continue_with_write_barrier);
     559             :         Goto(&store_field);
     560             :         BIND(&store_field);
     561             :       }
     562         124 :       StoreObjectFieldNoWriteBarrier(copy, offset.value(), field);
     563         496 :       offset.Bind(IntPtrAdd(offset.value(), IntPtrConstant(kPointerSize)));
     564         248 :       Branch(WordNotEqual(offset.value(), instance_size), &continue_fast,
     565         372 :              &done_init);
     566             :     }
     567             : 
     568             :     if (!may_use_mutable_heap_numbers) {
     569         124 :       BIND(&done_init);
     570         124 :       return copy;
     571             :     }
     572             :     // Continue initializing the literal after seeing the first sub-object
     573             :     // potentially causing allocation. In this case we prepare the new literal
     574             :     // by copying all pending fields over from the boilerplate and emit full
     575             :     // write barriers from here on.
     576             :     BIND(&continue_with_write_barrier);
     577             :     {
     578             :       Comment("Copy in-object properties slow");
     579             :       BuildFastLoop(offset.value(), instance_size,
     580             :                     [=](Node* offset) {
     581             :                       Node* field = LoadObjectField(boilerplate, offset);
     582             :                       StoreObjectFieldNoWriteBarrier(copy, offset, field);
     583             :                     },
     584             :                     kPointerSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
     585             :       Comment("Copy mutable HeapNumber values");
     586             :       BuildFastLoop(offset.value(), instance_size,
     587             :                     [=](Node* offset) {
     588             :                       Node* field = LoadObjectField(copy, offset);
     589             :                       Label copy_mutable_heap_number(this, Label::kDeferred),
     590             :                           continue_loop(this);
     591             :                       // We only have to clone complex field values.
     592             :                       GotoIf(TaggedIsSmi(field), &continue_loop);
     593             :                       Branch(IsMutableHeapNumber(field),
     594             :                              &copy_mutable_heap_number, &continue_loop);
     595             :                       BIND(&copy_mutable_heap_number);
     596             :                       {
     597             :                         Node* double_value = LoadHeapNumberValue(field);
     598             :                         Node* mutable_heap_number =
     599             :                             AllocateHeapNumberWithValue(double_value, MUTABLE);
     600             :                         StoreObjectField(copy, offset, mutable_heap_number);
     601             :                         Goto(&continue_loop);
     602             :                       }
     603             :                       BIND(&continue_loop);
     604             :                     },
     605             :                     kPointerSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
     606             :       Goto(&done_init);
     607             :     }
     608             :     BIND(&done_init);
     609             :   }
     610         124 :   return copy;
     611             : }
     612             : 
     613         186 : TF_BUILTIN(CreateShallowObjectLiteral, ConstructorBuiltinsAssembler) {
     614          31 :   Label call_runtime(this);
     615             :   Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
     616          62 :   Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
     617             :   Node* copy =
     618          31 :       EmitCreateShallowObjectLiteral(feedback_vector, slot, &call_runtime);
     619          31 :   Return(copy);
     620             : 
     621          31 :   BIND(&call_runtime);
     622             :   Node* boilerplate_description =
     623             :       Parameter(Descriptor::kBoilerplateDescription);
     624             :   Node* flags = Parameter(Descriptor::kFlags);
     625             :   Node* context = Parameter(Descriptor::kContext);
     626             :   TailCallRuntime(Runtime::kCreateObjectLiteral, context, feedback_vector,
     627          62 :                   SmiTag(slot), boilerplate_description, flags);
     628          31 : }
     629             : 
     630             : // Used by the CreateEmptyObjectLiteral bytecode and the Object constructor.
     631          62 : Node* ConstructorBuiltinsAssembler::EmitCreateEmptyObjectLiteral(
     632             :     Node* context) {
     633         124 :   Node* native_context = LoadNativeContext(context);
     634             :   Node* object_function =
     635         124 :       LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX);
     636             :   Node* map = LoadObjectField(object_function,
     637             :                               JSFunction::kPrototypeOrInitialMapOffset);
     638             :   CSA_ASSERT(this, IsMap(map));
     639             :   // Ensure that slack tracking is disabled for the map.
     640             :   STATIC_ASSERT(Map::kNoSlackTracking == 0);
     641             :   CSA_ASSERT(this,
     642             :              IsClearWord32<Map::ConstructionCounter>(LoadMapBitField3(map)));
     643         124 :   Node* empty_fixed_array = EmptyFixedArrayConstant();
     644             :   Node* result =
     645          62 :       AllocateJSObjectFromMap(map, empty_fixed_array, empty_fixed_array);
     646          62 :   return result;
     647             : }
     648             : 
     649         155 : TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) {
     650             :   int const kValueArg = 0;
     651             :   Node* argc =
     652          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
     653          31 :   CodeStubArguments args(this, argc);
     654          62 :   Node* value = args.GetOptionalArgumentValue(kValueArg);
     655             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     656             : 
     657             :   CSA_ASSERT(this, IsUndefined(Parameter(BuiltinDescriptor::kNewTarget)));
     658             : 
     659             :   Label return_to_object(this);
     660             : 
     661         124 :   GotoIf(Word32And(IsNotUndefined(value), IsNotNull(value)), &return_to_object);
     662             : 
     663          31 :   args.PopAndReturn(EmitCreateEmptyObjectLiteral(context));
     664             : 
     665          31 :   BIND(&return_to_object);
     666          31 :   args.PopAndReturn(CallBuiltin(Builtins::kToObject, context, value));
     667          31 : }
     668             : 
     669         155 : TF_BUILTIN(ObjectConstructor_ConstructStub, ConstructorBuiltinsAssembler) {
     670             :   int const kValueArg = 0;
     671             :   Node* argc =
     672          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
     673          31 :   CodeStubArguments args(this, argc);
     674          62 :   Node* value = args.GetOptionalArgumentValue(kValueArg);
     675             : 
     676             :   Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
     677          31 :                                MachineType::TaggedPointer());
     678             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
     679             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     680             : 
     681             :   CSA_ASSERT(this, IsNotUndefined(new_target));
     682             : 
     683             :   Label return_to_object(this);
     684             : 
     685          31 :   GotoIf(Word32And(WordEqual(target, new_target),
     686         186 :                    Word32And(IsNotUndefined(value), IsNotNull(value))),
     687          62 :          &return_to_object);
     688          31 :   args.PopAndReturn(EmitFastNewObject(context, target, new_target));
     689             : 
     690          31 :   BIND(&return_to_object);
     691          31 :   args.PopAndReturn(CallBuiltin(Builtins::kToObject, context, value));
     692          31 : }
     693             : 
     694         155 : TF_BUILTIN(NumberConstructor, ConstructorBuiltinsAssembler) {
     695             :   Node* argc =
     696          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
     697          31 :   CodeStubArguments args(this, argc);
     698             : 
     699             :   Label return_zero(this);
     700             : 
     701          93 :   GotoIf(IntPtrEqual(IntPtrConstant(0), argc), &return_zero);
     702             : 
     703             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     704          93 :   args.PopAndReturn(ToNumber(context, args.AtIndex(0)));
     705             : 
     706          31 :   BIND(&return_zero);
     707          62 :   args.PopAndReturn(SmiConstant(0));
     708          31 : }
     709             : 
     710         155 : TF_BUILTIN(NumberConstructor_ConstructStub, ConstructorBuiltinsAssembler) {
     711             :   Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
     712          31 :                                MachineType::TaggedPointer());
     713             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
     714             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     715             : 
     716             :   Node* argc =
     717          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
     718             :   CodeStubArguments args(this, argc);
     719             : 
     720          31 :   Label return_zero(this), wrap(this);
     721             : 
     722          62 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     723             : 
     724          93 :   GotoIf(IntPtrEqual(IntPtrConstant(0), argc), &return_zero);
     725             :   {
     726          93 :     var_result.Bind(ToNumber(context, args.AtIndex(0)));
     727          31 :     Goto(&wrap);
     728             :   }
     729             : 
     730          31 :   BIND(&return_zero);
     731             :   {
     732          62 :     var_result.Bind(SmiConstant(0));
     733          31 :     Goto(&wrap);
     734             :   }
     735             : 
     736          31 :   BIND(&wrap);
     737             :   {
     738          31 :     Node* result = EmitFastNewObject(context, target, new_target);
     739          31 :     StoreObjectField(result, JSValue::kValueOffset, var_result.value());
     740          31 :     args.PopAndReturn(result);
     741          31 :   }
     742          31 : }
     743             : 
     744          62 : Node* ConstructorBuiltinsAssembler::EmitConstructString(Node* argc,
     745             :                                                         CodeStubArguments& args,
     746             :                                                         Node* context,
     747             :                                                         bool convert_symbol) {
     748          62 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     749             : 
     750          62 :   Label return_empty_string(this), to_string(this),
     751          62 :       check_symbol(this, Label::kDeferred), done(this);
     752             : 
     753         186 :   GotoIf(IntPtrEqual(IntPtrConstant(0), argc), &return_empty_string);
     754             : 
     755         124 :   Node* argument = args.AtIndex(0);
     756             : 
     757         124 :   GotoIf(TaggedIsSmi(argument), &to_string);
     758             : 
     759         124 :   Node* instance_type = LoadInstanceType(argument);
     760             : 
     761          62 :   Label* non_string = convert_symbol ? &check_symbol : &to_string;
     762         124 :   GotoIfNot(IsStringInstanceType(instance_type), non_string);
     763             :   {
     764          62 :     var_result.Bind(argument);
     765          62 :     Goto(&done);
     766             :   }
     767             : 
     768          62 :   if (convert_symbol) {
     769          31 :     BIND(&check_symbol);
     770          62 :     GotoIfNot(IsSymbolInstanceType(instance_type), &to_string);
     771             :     {
     772             :       var_result.Bind(
     773          31 :           CallRuntime(Runtime::kSymbolDescriptiveString, context, argument));
     774          31 :       Goto(&done);
     775             :     }
     776             :   }
     777             : 
     778          62 :   BIND(&to_string);
     779             :   {
     780         124 :     var_result.Bind(ToString(context, argument));
     781          62 :     Goto(&done);
     782             :   }
     783             : 
     784          62 :   BIND(&return_empty_string);
     785             :   {
     786         124 :     var_result.Bind(EmptyStringConstant());
     787          62 :     Goto(&done);
     788             :   }
     789             : 
     790          62 :   BIND(&done);
     791         124 :   return var_result.value();
     792             : }
     793             : 
     794         124 : TF_BUILTIN(StringConstructor, ConstructorBuiltinsAssembler) {
     795             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     796             :   Node* argc =
     797          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
     798          31 :   CodeStubArguments args(this, argc);
     799             : 
     800          31 :   args.PopAndReturn(EmitConstructString(argc, args, context, true));
     801          31 : }
     802             : 
     803         155 : TF_BUILTIN(StringConstructor_ConstructStub, ConstructorBuiltinsAssembler) {
     804             :   Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
     805          31 :                                MachineType::TaggedPointer());
     806             :   Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
     807             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     808             : 
     809             :   Node* argc =
     810          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
     811             :   CodeStubArguments args(this, argc);
     812             : 
     813          31 :   Node* string = EmitConstructString(argc, args, context, false);
     814          31 :   Node* result = EmitFastNewObject(context, target, new_target);
     815          31 :   StoreObjectField(result, JSValue::kValueOffset, string);
     816          31 :   args.PopAndReturn(result);
     817          31 : }
     818             : 
     819             : }  // namespace internal
     820             : }  // namespace v8

Generated by: LCOV version 1.10