LCOV - code coverage report
Current view: top level - src - code-stubs.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 224 274 81.8 %
Date: 2017-10-20 Functions: 53 65 81.5 %

          Line data    Source code
       1             : // Copyright 2012 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/code-stubs.h"
       6             : 
       7             : #include <sstream>
       8             : 
       9             : #include "src/arguments.h"
      10             : #include "src/assembler-inl.h"
      11             : #include "src/ast/ast.h"
      12             : #include "src/bootstrapper.h"
      13             : #include "src/code-factory.h"
      14             : #include "src/code-stub-assembler.h"
      15             : #include "src/code-stubs-utils.h"
      16             : #include "src/counters.h"
      17             : #include "src/factory.h"
      18             : #include "src/gdb-jit.h"
      19             : #include "src/heap/heap-inl.h"
      20             : #include "src/ic/ic-stats.h"
      21             : #include "src/ic/ic.h"
      22             : #include "src/macro-assembler.h"
      23             : #include "src/objects-inl.h"
      24             : #include "src/tracing/tracing-category-observer.h"
      25             : 
      26             : namespace v8 {
      27             : namespace internal {
      28             : 
      29             : using compiler::CodeAssemblerState;
      30             : 
      31           0 : CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
      32             :     : isolate_(stub->isolate()),
      33           0 :       call_descriptor_(stub->GetCallInterfaceDescriptor()),
      34             :       stack_parameter_count_(no_reg),
      35             :       hint_stack_parameter_count_(-1),
      36             :       function_mode_(NOT_JS_FUNCTION_STUB_MODE),
      37             :       deoptimization_handler_(nullptr),
      38             :       miss_handler_(),
      39           0 :       has_miss_handler_(false) {
      40           0 :   stub->InitializeDescriptor(this);
      41           0 : }
      42             : 
      43           0 : CodeStubDescriptor::CodeStubDescriptor(Isolate* isolate, uint32_t stub_key)
      44             :     : isolate_(isolate),
      45             :       stack_parameter_count_(no_reg),
      46             :       hint_stack_parameter_count_(-1),
      47             :       function_mode_(NOT_JS_FUNCTION_STUB_MODE),
      48             :       deoptimization_handler_(nullptr),
      49             :       miss_handler_(),
      50           0 :       has_miss_handler_(false) {
      51             :   CodeStub::InitializeDescriptor(isolate, stub_key, this);
      52           0 : }
      53             : 
      54             : 
      55           0 : void CodeStubDescriptor::Initialize(Address deoptimization_handler,
      56             :                                     int hint_stack_parameter_count,
      57             :                                     StubFunctionMode function_mode) {
      58           0 :   deoptimization_handler_ = deoptimization_handler;
      59           0 :   hint_stack_parameter_count_ = hint_stack_parameter_count;
      60           0 :   function_mode_ = function_mode;
      61           0 : }
      62             : 
      63             : 
      64           0 : void CodeStubDescriptor::Initialize(Register stack_parameter_count,
      65             :                                     Address deoptimization_handler,
      66             :                                     int hint_stack_parameter_count,
      67             :                                     StubFunctionMode function_mode) {
      68             :   Initialize(deoptimization_handler, hint_stack_parameter_count, function_mode);
      69           0 :   stack_parameter_count_ = stack_parameter_count;
      70           0 : }
      71             : 
      72             : 
      73     4980646 : bool CodeStub::FindCodeInCache(Code** code_out) {
      74     2490323 :   UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
      75     2490323 :   int index = stubs->FindEntry(isolate(), GetKey());
      76     2490326 :   if (index != UnseededNumberDictionary::kNotFound) {
      77     2446058 :     *code_out = Code::cast(stubs->ValueAt(index));
      78     2446058 :     return true;
      79             :   }
      80             :   return false;
      81             : }
      82             : 
      83             : 
      84      132804 : void CodeStub::RecordCodeGeneration(Handle<Code> code) {
      85       44268 :   std::ostringstream os;
      86             :   os << *this;
      87       88536 :   PROFILE(isolate(),
      88             :           CodeCreateEvent(CodeEventListener::STUB_TAG,
      89             :                           AbstractCode::cast(*code), os.str().c_str()));
      90             :   Counters* counters = isolate()->counters();
      91       44268 :   counters->total_stubs_code_size()->Increment(code->instruction_size());
      92             : #ifdef DEBUG
      93             :   code->VerifyEmbeddedObjects();
      94             : #endif
      95       44268 : }
      96             : 
      97             : 
      98           0 : void CodeStub::DeleteStubFromCacheForTesting() {
      99           0 :   Heap* heap = isolate_->heap();
     100             :   Handle<UnseededNumberDictionary> dict(heap->code_stubs());
     101             :   int entry = dict->FindEntry(GetKey());
     102             :   DCHECK_NE(UnseededNumberDictionary::kNotFound, entry);
     103           0 :   dict = UnseededNumberDictionary::DeleteEntry(dict, entry);
     104           0 :   heap->SetRootCodeStubs(*dict);
     105           0 : }
     106             : 
     107       20225 : Handle<Code> PlatformCodeStub::GenerateCode() {
     108       80900 :   Factory* factory = isolate()->factory();
     109             : 
     110             :   // Generate the new code.
     111       20225 :   MacroAssembler masm(isolate(), nullptr, 256, CodeObjectRequired::kYes);
     112             : 
     113             :   {
     114             :     // Update the static counter each time a new code stub is generated.
     115       20225 :     isolate()->counters()->code_stubs()->Increment();
     116             : 
     117             :     // Generate the code for the stub.
     118             :     // TODO(yangguo): remove this once we can serialize IC stubs.
     119             :     masm.enable_serializer();
     120             :     NoCurrentFrameScope scope(&masm);
     121       20225 :     Generate(&masm);
     122             :   }
     123             : 
     124             :   // Allocate the handler table.
     125       20225 :   Handle<HandlerTable> table = GenerateHandlerTable();
     126             : 
     127             :   // Create the code object.
     128             :   CodeDesc desc;
     129       20225 :   masm.GetCode(isolate(), &desc);
     130             :   // Copy the generated code into a heap object.
     131             :   Handle<Code> new_object = factory->NewCode(
     132             :       desc, Code::STUB, masm.CodeObject(), table, MaybeHandle<ByteArray>(),
     133       60675 :       DeoptimizationData::Empty(isolate()), NeedsImmovableCode());
     134       40450 :   return new_object;
     135             : }
     136             : 
     137             : 
     138     2623127 : Handle<Code> CodeStub::GetCode() {
     139     2534591 :   Heap* heap = isolate()->heap();
     140             :   Code* code;
     141     2490323 :   if (FindCodeInCache(&code)) {
     142             :     DCHECK(code->is_stub());
     143     2446058 :     return handle(code);
     144             :   }
     145             : 
     146             :   {
     147             :     HandleScope scope(isolate());
     148             :     // Canonicalize handles, so that we can share constant pool entries pointing
     149             :     // to code targets without dereferencing their handles.
     150       88536 :     CanonicalHandleScope canonical(isolate());
     151             : 
     152       44268 :     Handle<Code> new_object = GenerateCode();
     153             :     new_object->set_stub_key(GetKey());
     154       44268 :     RecordCodeGeneration(new_object);
     155             : 
     156             : #ifdef ENABLE_DISASSEMBLER
     157             :     if (FLAG_print_code_stubs) {
     158             :       CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
     159             :       OFStream os(trace_scope.file());
     160             :       std::ostringstream name;
     161             :       name << *this;
     162             :       new_object->Disassemble(name.str().c_str(), os);
     163             :       os << "\n";
     164             :     }
     165             : #endif
     166             : 
     167             :     // Update the dictionary and the root in Heap.
     168             :     Handle<UnseededNumberDictionary> dict = UnseededNumberDictionary::Set(
     169       44268 :         handle(heap->code_stubs()), GetKey(), new_object);
     170       44268 :     heap->SetRootCodeStubs(*dict);
     171       44268 :     code = *new_object;
     172             :   }
     173             : 
     174       44268 :   Activate(code);
     175             :   DCHECK(!NeedsImmovableCode() || Heap::IsImmovable(code) ||
     176             :          heap->code_space()->FirstPage()->Contains(code->address()));
     177       88536 :   return Handle<Code>(code, isolate());
     178             : }
     179             : 
     180       20948 : CodeStub::Major CodeStub::GetMajorKey(Code* code_stub) {
     181       20948 :   return MajorKeyFromKey(code_stub->stub_key());
     182             : }
     183             : 
     184       88484 : const char* CodeStub::MajorName(CodeStub::Major major_key) {
     185       88484 :   switch (major_key) {
     186             : #define DEF_CASE(name) case name: return #name "Stub";
     187        3480 :     CODE_STUB_LIST(DEF_CASE)
     188             : #undef DEF_CASE
     189             :     case NoCache:
     190          25 :       return "<NoCache>Stub";
     191             :     case NUMBER_OF_IDS:
     192           0 :       UNREACHABLE();
     193             :   }
     194           0 :   return nullptr;
     195             : }
     196             : 
     197             : 
     198       43493 : void CodeStub::PrintBaseName(std::ostream& os) const {  // NOLINT
     199       43493 :   os << MajorName(MajorKey());
     200       43493 : }
     201             : 
     202             : 
     203       43586 : void CodeStub::PrintName(std::ostream& os) const {  // NOLINT
     204       43586 :   PrintBaseName(os);
     205       43586 :   PrintState(os);
     206       43586 : }
     207             : 
     208             : 
     209          60 : void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
     210             :                         DispatchedCall call) {
     211          60 :   switch (MajorKeyFromKey(key)) {
     212             : #define DEF_CASE(NAME)             \
     213             :   case NAME: {                     \
     214             :     NAME##Stub stub(key, isolate); \
     215             :     CodeStub* pstub = &stub;       \
     216             :     call(pstub, value_out);        \
     217             :     break;                         \
     218             :   }
     219          60 :     CODE_STUB_LIST(DEF_CASE)
     220             : #undef DEF_CASE
     221             :     case NUMBER_OF_IDS:
     222             :     case NoCache:
     223           0 :       UNREACHABLE();
     224             :       break;
     225             :   }
     226          60 : }
     227             : 
     228       20163 : Handle<HandlerTable> PlatformCodeStub::GenerateHandlerTable() {
     229       20163 :   return HandlerTable::Empty(isolate());
     230             : }
     231             : 
     232           0 : static void InitializeDescriptorDispatchedCall(CodeStub* stub,
     233             :                                                void** value_out) {
     234             :   CodeStubDescriptor* descriptor_out =
     235             :       reinterpret_cast<CodeStubDescriptor*>(value_out);
     236           0 :   stub->InitializeDescriptor(descriptor_out);
     237           0 :   descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
     238           0 : }
     239             : 
     240             : 
     241           0 : void CodeStub::InitializeDescriptor(Isolate* isolate, uint32_t key,
     242             :                                     CodeStubDescriptor* desc) {
     243             :   void** value_out = reinterpret_cast<void**>(desc);
     244           0 :   Dispatch(isolate, key, value_out, &InitializeDescriptorDispatchedCall);
     245           0 : }
     246             : 
     247             : 
     248          60 : void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
     249             :   Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
     250          60 :   *code_out = stub->GetCode();
     251          60 : }
     252             : 
     253             : 
     254          60 : MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
     255             :   HandleScope scope(isolate);
     256             :   Handle<Code> code;
     257             :   void** value_out = reinterpret_cast<void**>(&code);
     258          60 :   Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
     259         120 :   return scope.CloseAndEscape(code);
     260             : }
     261             : 
     262             : 
     263          93 : void StringAddStub::PrintBaseName(std::ostream& os) const {  // NOLINT
     264          93 :   os << "StringAddStub_" << flags() << "_" << pretenure_flag();
     265          93 : }
     266             : 
     267         372 : TF_STUB(StringAddStub, CodeStubAssembler) {
     268             :   StringAddFlags flags = stub->flags();
     269             :   PretenureFlag pretenure_flag = stub->pretenure_flag();
     270             : 
     271             :   Node* left = Parameter(Descriptor::kLeft);
     272             :   Node* right = Parameter(Descriptor::kRight);
     273             :   Node* context = Parameter(Descriptor::kContext);
     274             : 
     275          93 :   if ((flags & STRING_ADD_CHECK_LEFT) != 0) {
     276             :     DCHECK_NE(flags & STRING_ADD_CONVERT, 0);
     277             :     // TODO(danno): The ToString and JSReceiverToPrimitive below could be
     278             :     // combined to avoid duplicate smi and instance type checks.
     279          93 :     left = ToString(context, JSReceiverToPrimitive(context, left));
     280             :   }
     281          93 :   if ((flags & STRING_ADD_CHECK_RIGHT) != 0) {
     282             :     DCHECK_NE(flags & STRING_ADD_CONVERT, 0);
     283             :     // TODO(danno): The ToString and JSReceiverToPrimitive below could be
     284             :     // combined to avoid duplicate smi and instance type checks.
     285          93 :     right = ToString(context, JSReceiverToPrimitive(context, right));
     286             :   }
     287             : 
     288          93 :   if ((flags & STRING_ADD_CHECK_BOTH) == 0) {
     289             :     CodeStubAssembler::AllocationFlag allocation_flags =
     290             :         (pretenure_flag == TENURED) ? CodeStubAssembler::kPretenured
     291          31 :                                     : CodeStubAssembler::kNone;
     292          62 :     Return(StringAdd(context, left, right, allocation_flags));
     293             :   } else {
     294             :     Callable callable = CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE,
     295          62 :                                                pretenure_flag);
     296          62 :     TailCallStub(callable, context, left, right);
     297             :   }
     298          93 : }
     299             : 
     300       24043 : Handle<Code> TurboFanCodeStub::GenerateCode() {
     301       48086 :   const char* name = CodeStub::MajorName(MajorKey());
     302       24043 :   Zone zone(isolate()->allocator(), ZONE_NAME);
     303       24043 :   CallInterfaceDescriptor descriptor(GetCallInterfaceDescriptor());
     304             :   compiler::CodeAssemblerState state(isolate(), &zone, descriptor, Code::STUB,
     305       48086 :                                      name);
     306       24043 :   GenerateAssembly(&state);
     307       48086 :   return compiler::CodeAssembler::GenerateCode(&state);
     308             : }
     309             : 
     310        5280 : TF_STUB(ElementsTransitionAndStoreStub, CodeStubAssembler) {
     311             :   Node* receiver = Parameter(Descriptor::kReceiver);
     312             :   Node* key = Parameter(Descriptor::kName);
     313             :   Node* value = Parameter(Descriptor::kValue);
     314             :   Node* map = Parameter(Descriptor::kMap);
     315             :   Node* slot = Parameter(Descriptor::kSlot);
     316             :   Node* vector = Parameter(Descriptor::kVector);
     317             :   Node* context = Parameter(Descriptor::kContext);
     318             : 
     319             :   Comment(
     320             :       "ElementsTransitionAndStoreStub: from_kind=%s, to_kind=%s,"
     321             :       " is_jsarray=%d, store_mode=%d",
     322             :       ElementsKindToString(stub->from_kind()),
     323             :       ElementsKindToString(stub->to_kind()), stub->is_jsarray(),
     324        3520 :       stub->store_mode());
     325             : 
     326             :   Label miss(this);
     327             : 
     328             :   if (FLAG_trace_elements_transitions) {
     329             :     // Tracing elements transitions is the job of the runtime.
     330             :     Goto(&miss);
     331             :   } else {
     332             :     TransitionElementsKind(receiver, map, stub->from_kind(), stub->to_kind(),
     333        1760 :                            stub->is_jsarray(), &miss);
     334             :     EmitElementStore(receiver, key, value, stub->is_jsarray(), stub->to_kind(),
     335         880 :                      stub->store_mode(), &miss);
     336         880 :     Return(value);
     337             :   }
     338             : 
     339         880 :   BIND(&miss);
     340             :   {
     341         880 :     Comment("Miss");
     342             :     TailCallRuntime(Runtime::kElementsTransitionAndStoreIC_Miss, context,
     343         880 :                     receiver, key, value, map, slot, vector);
     344         880 :   }
     345         880 : }
     346             : 
     347          93 : TF_STUB(TransitionElementsKindStub, CodeStubAssembler) {
     348             :   Node* context = Parameter(Descriptor::kContext);
     349             :   Node* object = Parameter(Descriptor::kObject);
     350             :   Node* new_map = Parameter(Descriptor::kMap);
     351             : 
     352             :   Label bailout(this);
     353             :   TransitionElementsKind(object, new_map, stub->from_kind(), stub->to_kind(),
     354          62 :                          stub->is_jsarray(), &bailout);
     355             :   Return(object);
     356             : 
     357          31 :   BIND(&bailout);
     358             :   {
     359          31 :     Comment("Call runtime");
     360             :     TailCallRuntime(Runtime::kTransitionElementsKind, context, object, new_map);
     361          31 :   }
     362          31 : }
     363             : 
     364             : // TODO(ishell): move to builtins.
     365          93 : TF_STUB(NumberToStringStub, CodeStubAssembler) {
     366             :   Node* context = Parameter(Descriptor::kContext);
     367             :   Node* argument = Parameter(Descriptor::kArgument);
     368          62 :   Return(NumberToString(context, argument));
     369          31 : }
     370             : 
     371             : // TODO(ishell): move to builtins-handler-gen.
     372         885 : TF_STUB(KeyedLoadSloppyArgumentsStub, CodeStubAssembler) {
     373             :   Node* receiver = Parameter(Descriptor::kReceiver);
     374             :   Node* key = Parameter(Descriptor::kName);
     375             :   Node* slot = Parameter(Descriptor::kSlot);
     376             :   Node* vector = Parameter(Descriptor::kVector);
     377             :   Node* context = Parameter(Descriptor::kContext);
     378             : 
     379             :   Label miss(this);
     380             : 
     381         295 :   Node* result = LoadKeyedSloppyArguments(receiver, key, &miss);
     382         295 :   Return(result);
     383             : 
     384         295 :   BIND(&miss);
     385             :   {
     386         295 :     Comment("Miss");
     387             :     TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, slot,
     388             :                     vector);
     389         295 :   }
     390         295 : }
     391             : 
     392             : // TODO(ishell): move to builtins-handler-gen.
     393           0 : TF_STUB(KeyedStoreSloppyArgumentsStub, CodeStubAssembler) {
     394             :   Node* receiver = Parameter(Descriptor::kReceiver);
     395             :   Node* key = Parameter(Descriptor::kName);
     396             :   Node* value = Parameter(Descriptor::kValue);
     397             :   Node* slot = Parameter(Descriptor::kSlot);
     398             :   Node* vector = Parameter(Descriptor::kVector);
     399             :   Node* context = Parameter(Descriptor::kContext);
     400             : 
     401             :   Label miss(this);
     402             : 
     403           0 :   StoreKeyedSloppyArguments(receiver, key, value, &miss);
     404           0 :   Return(value);
     405             : 
     406           0 :   BIND(&miss);
     407             :   {
     408           0 :     Comment("Miss");
     409             :     TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector,
     410             :                     receiver, key);
     411           0 :   }
     412           0 : }
     413             : 
     414       69732 : TF_STUB(LoadScriptContextFieldStub, CodeStubAssembler) {
     415             :   Comment("LoadScriptContextFieldStub: context_index=%d, slot=%d",
     416       69732 :           stub->context_index(), stub->slot_index());
     417             : 
     418             :   Node* context = Parameter(Descriptor::kContext);
     419             : 
     420       17433 :   Node* script_context = LoadScriptContext(context, stub->context_index());
     421       17433 :   Node* result = LoadFixedArrayElement(script_context, stub->slot_index());
     422       17433 :   Return(result);
     423       17433 : }
     424             : 
     425         116 : TF_STUB(StoreScriptContextFieldStub, CodeStubAssembler) {
     426             :   Comment("StoreScriptContextFieldStub: context_index=%d, slot=%d",
     427         116 :           stub->context_index(), stub->slot_index());
     428             : 
     429             :   Node* value = Parameter(Descriptor::kValue);
     430             :   Node* context = Parameter(Descriptor::kContext);
     431             : 
     432          29 :   Node* script_context = LoadScriptContext(context, stub->context_index());
     433          29 :   StoreFixedArrayElement(script_context, IntPtrConstant(stub->slot_index()),
     434          58 :                          value);
     435          29 :   Return(value);
     436          29 : }
     437             : 
     438             : // TODO(ishell): move to builtins-handler-gen.
     439         249 : TF_STUB(StoreInterceptorStub, CodeStubAssembler) {
     440             :   Node* receiver = Parameter(Descriptor::kReceiver);
     441             :   Node* name = Parameter(Descriptor::kName);
     442             :   Node* value = Parameter(Descriptor::kValue);
     443             :   Node* slot = Parameter(Descriptor::kSlot);
     444             :   Node* vector = Parameter(Descriptor::kVector);
     445             :   Node* context = Parameter(Descriptor::kContext);
     446             :   TailCallRuntime(Runtime::kStorePropertyWithInterceptor, context, value, slot,
     447             :                   vector, receiver, name);
     448          83 : }
     449             : 
     450             : // TODO(ishell): move to builtins-handler-gen.
     451         168 : TF_STUB(LoadIndexedInterceptorStub, CodeStubAssembler) {
     452             :   Node* receiver = Parameter(Descriptor::kReceiver);
     453             :   Node* key = Parameter(Descriptor::kName);
     454             :   Node* slot = Parameter(Descriptor::kSlot);
     455             :   Node* vector = Parameter(Descriptor::kVector);
     456             :   Node* context = Parameter(Descriptor::kContext);
     457             : 
     458          56 :   Label if_keyispositivesmi(this), if_keyisinvalid(this);
     459         112 :   Branch(TaggedIsPositiveSmi(key), &if_keyispositivesmi, &if_keyisinvalid);
     460          56 :   BIND(&if_keyispositivesmi);
     461             :   TailCallRuntime(Runtime::kLoadElementWithInterceptor, context, receiver, key);
     462             : 
     463          56 :   BIND(&if_keyisinvalid);
     464             :   TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, slot,
     465          56 :                   vector);
     466          56 : }
     467             : 
     468          62 : Handle<HandlerTable> JSEntryStub::GenerateHandlerTable() {
     469             :   Handle<FixedArray> handler_table =
     470          62 :       isolate()->factory()->NewFixedArray(1, TENURED);
     471          62 :   handler_table->set(0, Smi::FromInt(handler_offset_));
     472          62 :   return Handle<HandlerTable>::cast(handler_table);
     473             : }
     474             : 
     475             : 
     476             : // TODO(ishell): move to builtins.
     477         124 : TF_STUB(GetPropertyStub, CodeStubAssembler) {
     478          62 :   Label call_runtime(this, Label::kDeferred), return_undefined(this), end(this);
     479             : 
     480             :   Node* object = Parameter(Descriptor::kObject);
     481             :   Node* key = Parameter(Descriptor::kKey);
     482             :   Node* context = Parameter(Descriptor::kContext);
     483          62 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     484             : 
     485             :   CodeStubAssembler::LookupInHolder lookup_property_in_holder =
     486             :       [=, &var_result, &end](Node* receiver, Node* holder, Node* holder_map,
     487             :                              Node* holder_instance_type, Node* unique_name,
     488          31 :                              Label* next_holder, Label* if_bailout) {
     489          31 :         VARIABLE(var_value, MachineRepresentation::kTagged);
     490          62 :         Label if_found(this);
     491             :         TryGetOwnProperty(context, receiver, holder, holder_map,
     492             :                           holder_instance_type, unique_name, &if_found,
     493          31 :                           &var_value, next_holder, if_bailout);
     494          31 :         BIND(&if_found);
     495             :         {
     496          31 :           var_result.Bind(var_value.value());
     497          31 :           Goto(&end);
     498             :         }
     499          31 :       };
     500             : 
     501             :   CodeStubAssembler::LookupInHolder lookup_element_in_holder =
     502             :       [=](Node* receiver, Node* holder, Node* holder_map,
     503             :           Node* holder_instance_type, Node* index, Label* next_holder,
     504             :           Label* if_bailout) {
     505             :         // Not supported yet.
     506          31 :         Use(next_holder);
     507          31 :         Goto(if_bailout);
     508             :       };
     509             : 
     510             :   TryPrototypeChainLookup(object, key, lookup_property_in_holder,
     511             :                           lookup_element_in_holder, &return_undefined,
     512          31 :                           &call_runtime);
     513             : 
     514          31 :   BIND(&return_undefined);
     515             :   {
     516          62 :     var_result.Bind(UndefinedConstant());
     517          31 :     Goto(&end);
     518             :   }
     519             : 
     520          31 :   BIND(&call_runtime);
     521             :   {
     522          31 :     var_result.Bind(CallRuntime(Runtime::kGetProperty, context, object, key));
     523          31 :     Goto(&end);
     524             :   }
     525             : 
     526          31 :   BIND(&end);
     527          93 :   Return(var_result.value());
     528          31 : }
     529             : 
     530             : // TODO(ishell): move to builtins-handler-gen.
     531        1680 : TF_STUB(StoreSlowElementStub, CodeStubAssembler) {
     532             :   Node* receiver = Parameter(Descriptor::kReceiver);
     533             :   Node* name = Parameter(Descriptor::kName);
     534             :   Node* value = Parameter(Descriptor::kValue);
     535             :   Node* slot = Parameter(Descriptor::kSlot);
     536             :   Node* vector = Parameter(Descriptor::kVector);
     537             :   Node* context = Parameter(Descriptor::kContext);
     538             : 
     539             :   TailCallRuntime(Runtime::kKeyedStoreIC_Slow, context, value, slot, vector,
     540             :                   receiver, name);
     541         560 : }
     542             : 
     543       23406 : TF_STUB(StoreFastElementStub, CodeStubAssembler) {
     544             :   Comment("StoreFastElementStub: js_array=%d, elements_kind=%s, store_mode=%d",
     545             :           stub->is_js_array(), ElementsKindToString(stub->elements_kind()),
     546       11703 :           stub->store_mode());
     547             : 
     548             :   Node* receiver = Parameter(Descriptor::kReceiver);
     549             :   Node* key = Parameter(Descriptor::kName);
     550             :   Node* value = Parameter(Descriptor::kValue);
     551             :   Node* slot = Parameter(Descriptor::kSlot);
     552             :   Node* vector = Parameter(Descriptor::kVector);
     553             :   Node* context = Parameter(Descriptor::kContext);
     554             : 
     555             :   Label miss(this);
     556             : 
     557             :   EmitElementStore(receiver, key, value, stub->is_js_array(),
     558        3901 :                    stub->elements_kind(), stub->store_mode(), &miss);
     559        3901 :   Return(value);
     560             : 
     561        3901 :   BIND(&miss);
     562             :   {
     563        3901 :     Comment("Miss");
     564             :     TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector,
     565             :                     receiver, key);
     566        3901 :   }
     567        3901 : }
     568             : 
     569             : // static
     570          31 : void StoreFastElementStub::GenerateAheadOfTime(Isolate* isolate) {
     571          62 :   if (FLAG_minimal) return;
     572             :   StoreFastElementStub(isolate, false, HOLEY_ELEMENTS, STANDARD_STORE)
     573          62 :       .GetCode();
     574             :   StoreFastElementStub(isolate, false, HOLEY_ELEMENTS,
     575             :                        STORE_AND_GROW_NO_TRANSITION)
     576          62 :       .GetCode();
     577         217 :   for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
     578         186 :     ElementsKind kind = static_cast<ElementsKind>(i);
     579         372 :     StoreFastElementStub(isolate, true, kind, STANDARD_STORE).GetCode();
     580             :     StoreFastElementStub(isolate, true, kind, STORE_AND_GROW_NO_TRANSITION)
     581         372 :         .GetCode();
     582             :   }
     583             : }
     584             : 
     585             : 
     586           0 : void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
     587             :                                                intptr_t stack_pointer,
     588           0 :                                                Isolate* isolate) {
     589             :   FunctionEntryHook entry_hook = isolate->function_entry_hook();
     590             :   DCHECK_NOT_NULL(entry_hook);
     591           0 :   entry_hook(function, stack_pointer);
     592           0 : }
     593             : 
     594        1054 : TF_STUB(ArrayNoArgumentConstructorStub, CodeStubAssembler) {
     595             :   ElementsKind elements_kind = stub->elements_kind();
     596             :   Node* native_context = LoadObjectField(Parameter(Descriptor::kFunction),
     597         248 :                                          JSFunction::kContextOffset);
     598             :   bool track_allocation_site =
     599         372 :       AllocationSite::ShouldTrack(elements_kind) &&
     600             :       stub->override_mode() != DISABLE_ALLOCATION_SITES;
     601             :   Node* allocation_site =
     602         248 :       track_allocation_site ? Parameter(Descriptor::kAllocationSite) : nullptr;
     603         496 :   Node* array_map = LoadJSArrayElementsMap(elements_kind, native_context);
     604             :   Node* array =
     605             :       AllocateJSArray(elements_kind, array_map,
     606             :                       IntPtrConstant(JSArray::kPreallocatedArrayElements),
     607         744 :                       SmiConstant(0), allocation_site);
     608         248 :   Return(array);
     609         248 : }
     610             : 
     611         186 : TF_STUB(InternalArrayNoArgumentConstructorStub, CodeStubAssembler) {
     612             :   Node* array_map = LoadObjectField(Parameter(Descriptor::kFunction),
     613          62 :                                     JSFunction::kPrototypeOrInitialMapOffset);
     614             :   Node* array = AllocateJSArray(
     615             :       stub->elements_kind(), array_map,
     616         186 :       IntPtrConstant(JSArray::kPreallocatedArrayElements), SmiConstant(0));
     617          62 :   Return(array);
     618          62 : }
     619             : 
     620             : class ArrayConstructorAssembler : public CodeStubAssembler {
     621             :  public:
     622             :   typedef compiler::Node Node;
     623             : 
     624             :   explicit ArrayConstructorAssembler(compiler::CodeAssemblerState* state)
     625         310 :       : CodeStubAssembler(state) {}
     626             : 
     627             :   void GenerateConstructor(Node* context, Node* array_function, Node* array_map,
     628             :                            Node* array_size, Node* allocation_site,
     629             :                            ElementsKind elements_kind, AllocationSiteMode mode);
     630             : };
     631             : 
     632         310 : void ArrayConstructorAssembler::GenerateConstructor(
     633             :     Node* context, Node* array_function, Node* array_map, Node* array_size,
     634             :     Node* allocation_site, ElementsKind elements_kind,
     635             :     AllocationSiteMode mode) {
     636         310 :   Label ok(this);
     637         310 :   Label smi_size(this);
     638         310 :   Label small_smi_size(this);
     639         310 :   Label call_runtime(this, Label::kDeferred);
     640             : 
     641         620 :   Branch(TaggedIsSmi(array_size), &smi_size, &call_runtime);
     642             : 
     643         310 :   BIND(&smi_size);
     644             : 
     645         310 :   if (IsFastPackedElementsKind(elements_kind)) {
     646             :     Label abort(this, Label::kDeferred);
     647         465 :     Branch(SmiEqual(array_size, SmiConstant(0)), &small_smi_size, &abort);
     648             : 
     649         155 :     BIND(&abort);
     650         310 :     Node* reason = SmiConstant(kAllocatingNonEmptyPackedArray);
     651         155 :     TailCallRuntime(Runtime::kAbort, context, reason);
     652             :   } else {
     653             :     int element_size =
     654             :         IsDoubleElementsKind(elements_kind) ? kDoubleSize : kPointerSize;
     655             :     int max_fast_elements =
     656             :         (kMaxRegularHeapObjectSize - FixedArray::kHeaderSize - JSArray::kSize -
     657             :          AllocationMemento::kSize) /
     658             :         element_size;
     659             :     Branch(SmiAboveOrEqual(array_size, SmiConstant(max_fast_elements)),
     660         465 :            &call_runtime, &small_smi_size);
     661             :   }
     662             : 
     663         310 :   BIND(&small_smi_size);
     664             :   {
     665             :     Node* array = AllocateJSArray(
     666             :         elements_kind, array_map, array_size, array_size,
     667             :         mode == DONT_TRACK_ALLOCATION_SITE ? nullptr : allocation_site,
     668         310 :         CodeStubAssembler::SMI_PARAMETERS);
     669         310 :     Return(array);
     670             :   }
     671             : 
     672         310 :   BIND(&call_runtime);
     673             :   {
     674             :     TailCallRuntime(Runtime::kNewArray, context, array_function, array_size,
     675             :                     array_function, allocation_site);
     676         310 :   }
     677         310 : }
     678             : 
     679        1488 : TF_STUB(ArraySingleArgumentConstructorStub, ArrayConstructorAssembler) {
     680             :   ElementsKind elements_kind = stub->elements_kind();
     681             :   Node* context = Parameter(Descriptor::kContext);
     682             :   Node* function = Parameter(Descriptor::kFunction);
     683         248 :   Node* native_context = LoadObjectField(function, JSFunction::kContextOffset);
     684         496 :   Node* array_map = LoadJSArrayElementsMap(elements_kind, native_context);
     685             :   AllocationSiteMode mode = DONT_TRACK_ALLOCATION_SITE;
     686         248 :   if (stub->override_mode() == DONT_OVERRIDE) {
     687             :     mode = AllocationSite::ShouldTrack(elements_kind)
     688             :                ? TRACK_ALLOCATION_SITE
     689         186 :                : DONT_TRACK_ALLOCATION_SITE;
     690             :   }
     691             : 
     692             :   Node* array_size = Parameter(Descriptor::kArraySizeSmiParameter);
     693             :   Node* allocation_site = Parameter(Descriptor::kAllocationSite);
     694             : 
     695             :   GenerateConstructor(context, function, array_map, array_size, allocation_site,
     696         248 :                       elements_kind, mode);
     697         248 : }
     698             : 
     699         310 : TF_STUB(InternalArraySingleArgumentConstructorStub, ArrayConstructorAssembler) {
     700             :   Node* context = Parameter(Descriptor::kContext);
     701             :   Node* function = Parameter(Descriptor::kFunction);
     702             :   Node* array_map =
     703          62 :       LoadObjectField(function, JSFunction::kPrototypeOrInitialMapOffset);
     704             :   Node* array_size = Parameter(Descriptor::kArraySizeSmiParameter);
     705         124 :   Node* allocation_site = UndefinedConstant();
     706             : 
     707             :   GenerateConstructor(context, function, array_map, array_size, allocation_site,
     708          62 :                       stub->elements_kind(), DONT_TRACK_ALLOCATION_SITE);
     709          62 : }
     710             : 
     711           0 : TF_STUB(GrowArrayElementsStub, CodeStubAssembler) {
     712           0 :   Label runtime(this, CodeStubAssembler::Label::kDeferred);
     713             : 
     714             :   Node* object = Parameter(Descriptor::kObject);
     715             :   Node* key = Parameter(Descriptor::kKey);
     716             :   Node* context = Parameter(Descriptor::kContext);
     717             :   ElementsKind kind = stub->elements_kind();
     718             : 
     719           0 :   Node* elements = LoadElements(object);
     720             :   Node* new_elements =
     721           0 :       TryGrowElementsCapacity(object, elements, kind, key, &runtime);
     722           0 :   Return(new_elements);
     723             : 
     724           0 :   BIND(&runtime);
     725             :   // TODO(danno): Make this a tail call when the stub is only used from TurboFan
     726             :   // code. This musn't be a tail call for now, since the caller site in lithium
     727             :   // creates a safepoint. This safepoint musn't have a different number of
     728             :   // arguments on the stack in the case that a GC happens from the slow-case
     729             :   // allocation path (zero, since all the stubs inputs are in registers) and
     730             :   // when the call happens (it would be two in the tail call case due to the
     731             :   // tail call pushing the arguments on the stack for the runtime call). By not
     732             :   // tail-calling, the runtime call case also has zero arguments on the stack
     733             :   // for the stub frame.
     734           0 :   Return(CallRuntime(Runtime::kGrowArrayElements, context, object, key));
     735           0 : }
     736             : 
     737      443474 : ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
     738      443474 :     : PlatformCodeStub(isolate) {}
     739             : 
     740         153 : InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate)
     741         153 :     : PlatformCodeStub(isolate) {}
     742             : 
     743        1304 : CommonArrayConstructorStub::CommonArrayConstructorStub(
     744             :     Isolate* isolate, ElementsKind kind,
     745             :     AllocationSiteOverrideMode override_mode)
     746        1304 :     : TurboFanCodeStub(isolate) {
     747             :   // It only makes sense to override local allocation site behavior
     748             :   // if there is a difference between the global allocation site policy
     749             :   // for an ElementsKind and the desired usage of the stub.
     750             :   DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
     751             :          AllocationSite::ShouldTrack(kind));
     752             :   set_sub_minor_key(ElementsKindBits::encode(kind) |
     753        1304 :                     AllocationSiteOverrideModeBits::encode(override_mode));
     754        1304 : }
     755             : 
     756             : }  // namespace internal
     757             : }  // namespace v8

Generated by: LCOV version 1.10