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/gdb-jit.h"
18 #include "src/heap/heap-inl.h"
19 #include "src/ic/ic-stats.h"
20 #include "src/ic/ic.h"
21 #include "src/macro-assembler.h"
22 #include "src/objects-inl.h"
23 #include "src/objects/hash-table-inl.h"
24 #include "src/tracing/tracing-category-observer.h"
25
26 namespace v8 {
27 namespace internal {
28
29 using compiler::CodeAssemblerState;
30
CodeStubDescriptor(CodeStub * stub)31 CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
32 : isolate_(stub->isolate()),
33 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_(kNullAddress),
38 miss_handler_(),
39 has_miss_handler_(false) {
40 stub->InitializeDescriptor(this);
41 }
42
CodeStubDescriptor(Isolate * isolate,uint32_t stub_key)43 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_(kNullAddress),
49 miss_handler_(),
50 has_miss_handler_(false) {
51 CodeStub::InitializeDescriptor(isolate, stub_key, this);
52 }
53
54
Initialize(Address deoptimization_handler,int hint_stack_parameter_count,StubFunctionMode function_mode)55 void CodeStubDescriptor::Initialize(Address deoptimization_handler,
56 int hint_stack_parameter_count,
57 StubFunctionMode function_mode) {
58 deoptimization_handler_ = deoptimization_handler;
59 hint_stack_parameter_count_ = hint_stack_parameter_count;
60 function_mode_ = function_mode;
61 }
62
63
Initialize(Register stack_parameter_count,Address deoptimization_handler,int hint_stack_parameter_count,StubFunctionMode function_mode)64 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 stack_parameter_count_ = stack_parameter_count;
70 }
71
72
FindCodeInCache(Code ** code_out)73 bool CodeStub::FindCodeInCache(Code** code_out) {
74 SimpleNumberDictionary* stubs = isolate()->heap()->code_stubs();
75 int index = stubs->FindEntry(isolate(), GetKey());
76 if (index != SimpleNumberDictionary::kNotFound) {
77 *code_out = Code::cast(stubs->ValueAt(index));
78 return true;
79 }
80 return false;
81 }
82
83
RecordCodeGeneration(Handle<Code> code)84 void CodeStub::RecordCodeGeneration(Handle<Code> code) {
85 std::ostringstream os;
86 os << *this;
87 PROFILE(isolate(),
88 CodeCreateEvent(CodeEventListener::STUB_TAG,
89 AbstractCode::cast(*code), os.str().c_str()));
90 Counters* counters = isolate()->counters();
91 counters->total_stubs_code_size()->Increment(code->raw_instruction_size());
92 #ifdef DEBUG
93 code->VerifyEmbeddedObjects();
94 #endif
95 }
96
97
DeleteStubFromCacheForTesting()98 void CodeStub::DeleteStubFromCacheForTesting() {
99 Heap* heap = isolate_->heap();
100 Handle<SimpleNumberDictionary> dict(heap->code_stubs());
101 int entry = dict->FindEntry(GetKey());
102 DCHECK_NE(SimpleNumberDictionary::kNotFound, entry);
103 dict = SimpleNumberDictionary::DeleteEntry(dict, entry);
104 heap->SetRootCodeStubs(*dict);
105 }
106
GenerateCode()107 Handle<Code> PlatformCodeStub::GenerateCode() {
108 Factory* factory = isolate()->factory();
109
110 // Generate the new code.
111 MacroAssembler masm(isolate(), nullptr, 256, CodeObjectRequired::kYes);
112
113 {
114 // Update the static counter each time a new code stub is generated.
115 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 Generate(&masm);
122 }
123
124 // Generate the handler table.
125 int handler_table_offset = GenerateHandlerTable(&masm);
126
127 // Create the code object.
128 CodeDesc desc;
129 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(), Builtins::kNoBuiltinId,
133 MaybeHandle<ByteArray>(), DeoptimizationData::Empty(isolate()),
134 NeedsImmovableCode(), GetKey(), false, 0, 0, handler_table_offset);
135 return new_object;
136 }
137
138
GetCode()139 Handle<Code> CodeStub::GetCode() {
140 Heap* heap = isolate()->heap();
141 Code* code;
142 if (FindCodeInCache(&code)) {
143 DCHECK(code->is_stub());
144 return handle(code);
145 }
146
147 {
148 HandleScope scope(isolate());
149 // Canonicalize handles, so that we can share constant pool entries pointing
150 // to code targets without dereferencing their handles.
151 CanonicalHandleScope canonical(isolate());
152
153 Handle<Code> new_object = GenerateCode();
154 DCHECK_EQ(GetKey(), new_object->stub_key());
155 RecordCodeGeneration(new_object);
156
157 #ifdef ENABLE_DISASSEMBLER
158 if (FLAG_print_code_stubs) {
159 CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
160 OFStream os(trace_scope.file());
161 std::ostringstream name;
162 name << *this;
163 new_object->Disassemble(name.str().c_str(), os);
164 os << "\n";
165 }
166 #endif
167
168 // Update the dictionary and the root in Heap.
169 Handle<SimpleNumberDictionary> dict = SimpleNumberDictionary::Set(
170 handle(heap->code_stubs()), GetKey(), new_object);
171 heap->SetRootCodeStubs(*dict);
172 code = *new_object;
173 }
174
175 Activate(code);
176 DCHECK(!NeedsImmovableCode() || Heap::IsImmovable(code));
177 return Handle<Code>(code, isolate());
178 }
179
GetMajorKey(Code * code_stub)180 CodeStub::Major CodeStub::GetMajorKey(Code* code_stub) {
181 return MajorKeyFromKey(code_stub->stub_key());
182 }
183
MajorName(CodeStub::Major major_key)184 const char* CodeStub::MajorName(CodeStub::Major major_key) {
185 switch (major_key) {
186 #define DEF_CASE(name) case name: return #name "Stub";
187 CODE_STUB_LIST(DEF_CASE)
188 #undef DEF_CASE
189 case NoCache:
190 return "<NoCache>Stub";
191 case NUMBER_OF_IDS:
192 UNREACHABLE();
193 }
194 return nullptr;
195 }
196
197
PrintBaseName(std::ostream & os) const198 void CodeStub::PrintBaseName(std::ostream& os) const { // NOLINT
199 os << MajorName(MajorKey());
200 }
201
202
PrintName(std::ostream & os) const203 void CodeStub::PrintName(std::ostream& os) const { // NOLINT
204 PrintBaseName(os);
205 PrintState(os);
206 }
207
208
Dispatch(Isolate * isolate,uint32_t key,void ** value_out,DispatchedCall call)209 void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
210 DispatchedCall call) {
211 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 CODE_STUB_LIST(DEF_CASE)
220 #undef DEF_CASE
221 case NUMBER_OF_IDS:
222 case NoCache:
223 UNREACHABLE();
224 break;
225 }
226 }
227
GenerateHandlerTable(MacroAssembler * masm)228 int PlatformCodeStub::GenerateHandlerTable(MacroAssembler* masm) { return 0; }
229
InitializeDescriptorDispatchedCall(CodeStub * stub,void ** value_out)230 static void InitializeDescriptorDispatchedCall(CodeStub* stub,
231 void** value_out) {
232 CodeStubDescriptor* descriptor_out =
233 reinterpret_cast<CodeStubDescriptor*>(value_out);
234 stub->InitializeDescriptor(descriptor_out);
235 descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
236 }
237
238
InitializeDescriptor(Isolate * isolate,uint32_t key,CodeStubDescriptor * desc)239 void CodeStub::InitializeDescriptor(Isolate* isolate, uint32_t key,
240 CodeStubDescriptor* desc) {
241 void** value_out = reinterpret_cast<void**>(desc);
242 Dispatch(isolate, key, value_out, &InitializeDescriptorDispatchedCall);
243 }
244
245
GetCodeDispatchCall(CodeStub * stub,void ** value_out)246 void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
247 Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
248 *code_out = stub->GetCode();
249 }
250
251
GetCode(Isolate * isolate,uint32_t key)252 MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
253 HandleScope scope(isolate);
254 Handle<Code> code;
255 void** value_out = reinterpret_cast<void**>(&code);
256 Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
257 return scope.CloseAndEscape(code);
258 }
259
GenerateCode()260 Handle<Code> TurboFanCodeStub::GenerateCode() {
261 const char* name = CodeStub::MajorName(MajorKey());
262 Zone zone(isolate()->allocator(), ZONE_NAME);
263 CallInterfaceDescriptor descriptor(GetCallInterfaceDescriptor());
264 compiler::CodeAssemblerState state(
265 isolate(), &zone, descriptor, Code::STUB, name,
266 PoisoningMitigationLevel::kDontPoison, 1, GetKey());
267 GenerateAssembly(&state);
268 return compiler::CodeAssembler::GenerateCode(&state);
269 }
270
TF_STUB(ElementsTransitionAndStoreStub,CodeStubAssembler)271 TF_STUB(ElementsTransitionAndStoreStub, CodeStubAssembler) {
272 Node* receiver = Parameter(Descriptor::kReceiver);
273 Node* key = Parameter(Descriptor::kName);
274 Node* value = Parameter(Descriptor::kValue);
275 Node* map = Parameter(Descriptor::kMap);
276 Node* slot = Parameter(Descriptor::kSlot);
277 Node* vector = Parameter(Descriptor::kVector);
278 Node* context = Parameter(Descriptor::kContext);
279
280 Comment(
281 "ElementsTransitionAndStoreStub: from_kind=%s, to_kind=%s,"
282 " is_jsarray=%d, store_mode=%d",
283 ElementsKindToString(stub->from_kind()),
284 ElementsKindToString(stub->to_kind()), stub->is_jsarray(),
285 stub->store_mode());
286
287 Label miss(this);
288
289 if (FLAG_trace_elements_transitions) {
290 // Tracing elements transitions is the job of the runtime.
291 Goto(&miss);
292 } else {
293 TransitionElementsKind(receiver, map, stub->from_kind(), stub->to_kind(),
294 stub->is_jsarray(), &miss);
295 EmitElementStore(receiver, key, value, stub->is_jsarray(), stub->to_kind(),
296 stub->store_mode(), &miss, context);
297 Return(value);
298 }
299
300 BIND(&miss);
301 {
302 Comment("Miss");
303 TailCallRuntime(Runtime::kElementsTransitionAndStoreIC_Miss, context,
304 receiver, key, value, map, slot, vector);
305 }
306 }
307
TF_STUB(TransitionElementsKindStub,CodeStubAssembler)308 TF_STUB(TransitionElementsKindStub, CodeStubAssembler) {
309 Node* context = Parameter(Descriptor::kContext);
310 Node* object = Parameter(Descriptor::kObject);
311 Node* new_map = Parameter(Descriptor::kMap);
312
313 Label bailout(this);
314 TransitionElementsKind(object, new_map, stub->from_kind(), stub->to_kind(),
315 stub->is_jsarray(), &bailout);
316 Return(object);
317
318 BIND(&bailout);
319 {
320 Comment("Call runtime");
321 TailCallRuntime(Runtime::kTransitionElementsKind, context, object, new_map);
322 }
323 }
324
325 // TODO(ishell): move to builtins-handler-gen.
TF_STUB(KeyedLoadSloppyArgumentsStub,CodeStubAssembler)326 TF_STUB(KeyedLoadSloppyArgumentsStub, CodeStubAssembler) {
327 Node* receiver = Parameter(Descriptor::kReceiver);
328 Node* key = Parameter(Descriptor::kName);
329 Node* slot = Parameter(Descriptor::kSlot);
330 Node* vector = Parameter(Descriptor::kVector);
331 Node* context = Parameter(Descriptor::kContext);
332
333 Label miss(this);
334
335 Node* result = LoadKeyedSloppyArguments(receiver, key, &miss);
336 Return(result);
337
338 BIND(&miss);
339 {
340 Comment("Miss");
341 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, slot,
342 vector);
343 }
344 }
345
346 // TODO(ishell): move to builtins-handler-gen.
TF_STUB(KeyedStoreSloppyArgumentsStub,CodeStubAssembler)347 TF_STUB(KeyedStoreSloppyArgumentsStub, CodeStubAssembler) {
348 Node* receiver = Parameter(Descriptor::kReceiver);
349 Node* key = Parameter(Descriptor::kName);
350 Node* value = Parameter(Descriptor::kValue);
351 Node* slot = Parameter(Descriptor::kSlot);
352 Node* vector = Parameter(Descriptor::kVector);
353 Node* context = Parameter(Descriptor::kContext);
354
355 Label miss(this);
356
357 StoreKeyedSloppyArguments(receiver, key, value, &miss);
358 Return(value);
359
360 BIND(&miss);
361 {
362 Comment("Miss");
363 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector,
364 receiver, key);
365 }
366 }
367
368 // TODO(ishell): move to builtins-handler-gen.
TF_STUB(StoreInterceptorStub,CodeStubAssembler)369 TF_STUB(StoreInterceptorStub, CodeStubAssembler) {
370 Node* receiver = Parameter(Descriptor::kReceiver);
371 Node* name = Parameter(Descriptor::kName);
372 Node* value = Parameter(Descriptor::kValue);
373 Node* slot = Parameter(Descriptor::kSlot);
374 Node* vector = Parameter(Descriptor::kVector);
375 Node* context = Parameter(Descriptor::kContext);
376 TailCallRuntime(Runtime::kStorePropertyWithInterceptor, context, value, slot,
377 vector, receiver, name);
378 }
379
380 // TODO(ishell): move to builtins-handler-gen.
TF_STUB(LoadIndexedInterceptorStub,CodeStubAssembler)381 TF_STUB(LoadIndexedInterceptorStub, CodeStubAssembler) {
382 Node* receiver = Parameter(Descriptor::kReceiver);
383 Node* key = Parameter(Descriptor::kName);
384 Node* slot = Parameter(Descriptor::kSlot);
385 Node* vector = Parameter(Descriptor::kVector);
386 Node* context = Parameter(Descriptor::kContext);
387
388 Label if_keyispositivesmi(this), if_keyisinvalid(this);
389 Branch(TaggedIsPositiveSmi(key), &if_keyispositivesmi, &if_keyisinvalid);
390 BIND(&if_keyispositivesmi);
391 TailCallRuntime(Runtime::kLoadElementWithInterceptor, context, receiver, key);
392
393 BIND(&if_keyisinvalid);
394 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, slot,
395 vector);
396 }
397
GenerateHandlerTable(MacroAssembler * masm)398 int JSEntryStub::GenerateHandlerTable(MacroAssembler* masm) {
399 int handler_table_offset = HandlerTable::EmitReturnTableStart(masm, 1);
400 HandlerTable::EmitReturnEntry(masm, 0, handler_offset_);
401 return handler_table_offset;
402 }
403
404 // TODO(ishell): move to builtins-handler-gen.
TF_STUB(StoreSlowElementStub,CodeStubAssembler)405 TF_STUB(StoreSlowElementStub, CodeStubAssembler) {
406 Node* receiver = Parameter(Descriptor::kReceiver);
407 Node* name = Parameter(Descriptor::kName);
408 Node* value = Parameter(Descriptor::kValue);
409 Node* slot = Parameter(Descriptor::kSlot);
410 Node* vector = Parameter(Descriptor::kVector);
411 Node* context = Parameter(Descriptor::kContext);
412
413 TailCallRuntime(Runtime::kKeyedStoreIC_Slow, context, value, slot, vector,
414 receiver, name);
415 }
416
TF_STUB(StoreInArrayLiteralSlowStub,CodeStubAssembler)417 TF_STUB(StoreInArrayLiteralSlowStub, CodeStubAssembler) {
418 Node* array = Parameter(Descriptor::kReceiver);
419 Node* index = Parameter(Descriptor::kName);
420 Node* value = Parameter(Descriptor::kValue);
421 Node* context = Parameter(Descriptor::kContext);
422 TailCallRuntime(Runtime::kStoreInArrayLiteralIC_Slow, context, value, array,
423 index);
424 }
425
TF_STUB(StoreFastElementStub,CodeStubAssembler)426 TF_STUB(StoreFastElementStub, CodeStubAssembler) {
427 Comment("StoreFastElementStub: js_array=%d, elements_kind=%s, store_mode=%d",
428 stub->is_js_array(), ElementsKindToString(stub->elements_kind()),
429 stub->store_mode());
430
431 Node* receiver = Parameter(Descriptor::kReceiver);
432 Node* key = Parameter(Descriptor::kName);
433 Node* value = Parameter(Descriptor::kValue);
434 Node* slot = Parameter(Descriptor::kSlot);
435 Node* vector = Parameter(Descriptor::kVector);
436 Node* context = Parameter(Descriptor::kContext);
437
438 Label miss(this);
439
440 EmitElementStore(receiver, key, value, stub->is_js_array(),
441 stub->elements_kind(), stub->store_mode(), &miss, context);
442 Return(value);
443
444 BIND(&miss);
445 {
446 Comment("Miss");
447 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector,
448 receiver, key);
449 }
450 }
451
452 // static
GenerateAheadOfTime(Isolate * isolate)453 void StoreFastElementStub::GenerateAheadOfTime(Isolate* isolate) {
454 if (FLAG_minimal) return;
455 StoreFastElementStub(isolate, false, HOLEY_ELEMENTS, STANDARD_STORE)
456 .GetCode();
457 StoreFastElementStub(isolate, false, HOLEY_ELEMENTS,
458 STORE_AND_GROW_NO_TRANSITION_HANDLE_COW)
459 .GetCode();
460 for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
461 ElementsKind kind = static_cast<ElementsKind>(i);
462 StoreFastElementStub(isolate, true, kind, STANDARD_STORE).GetCode();
463 StoreFastElementStub(isolate, true, kind,
464 STORE_AND_GROW_NO_TRANSITION_HANDLE_COW)
465 .GetCode();
466 }
467 }
468
469
EntryHookTrampoline(intptr_t function,intptr_t stack_pointer,Isolate * isolate)470 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
471 intptr_t stack_pointer,
472 Isolate* isolate) {
473 FunctionEntryHook entry_hook = isolate->function_entry_hook();
474 DCHECK_NOT_NULL(entry_hook);
475 entry_hook(function, stack_pointer);
476 }
477
TF_STUB(ArrayNoArgumentConstructorStub,CodeStubAssembler)478 TF_STUB(ArrayNoArgumentConstructorStub, CodeStubAssembler) {
479 ElementsKind elements_kind = stub->elements_kind();
480 Node* native_context = LoadObjectField(Parameter(Descriptor::kFunction),
481 JSFunction::kContextOffset);
482 bool track_allocation_site =
483 AllocationSite::ShouldTrack(elements_kind) &&
484 stub->override_mode() != DISABLE_ALLOCATION_SITES;
485 Node* allocation_site =
486 track_allocation_site ? Parameter(Descriptor::kAllocationSite) : nullptr;
487 Node* array_map = LoadJSArrayElementsMap(elements_kind, native_context);
488 Node* array =
489 AllocateJSArray(elements_kind, array_map,
490 IntPtrConstant(JSArray::kPreallocatedArrayElements),
491 SmiConstant(0), allocation_site);
492 Return(array);
493 }
494
TF_STUB(InternalArrayNoArgumentConstructorStub,CodeStubAssembler)495 TF_STUB(InternalArrayNoArgumentConstructorStub, CodeStubAssembler) {
496 Node* array_map = LoadObjectField(Parameter(Descriptor::kFunction),
497 JSFunction::kPrototypeOrInitialMapOffset);
498 Node* array = AllocateJSArray(
499 stub->elements_kind(), array_map,
500 IntPtrConstant(JSArray::kPreallocatedArrayElements), SmiConstant(0));
501 Return(array);
502 }
503
504 class ArrayConstructorAssembler : public CodeStubAssembler {
505 public:
506 typedef compiler::Node Node;
507
ArrayConstructorAssembler(compiler::CodeAssemblerState * state)508 explicit ArrayConstructorAssembler(compiler::CodeAssemblerState* state)
509 : CodeStubAssembler(state) {}
510
511 void GenerateConstructor(Node* context, Node* array_function, Node* array_map,
512 Node* array_size, Node* allocation_site,
513 ElementsKind elements_kind, AllocationSiteMode mode);
514 };
515
GenerateConstructor(Node * context,Node * array_function,Node * array_map,Node * array_size,Node * allocation_site,ElementsKind elements_kind,AllocationSiteMode mode)516 void ArrayConstructorAssembler::GenerateConstructor(
517 Node* context, Node* array_function, Node* array_map, Node* array_size,
518 Node* allocation_site, ElementsKind elements_kind,
519 AllocationSiteMode mode) {
520 Label ok(this);
521 Label smi_size(this);
522 Label small_smi_size(this);
523 Label call_runtime(this, Label::kDeferred);
524
525 Branch(TaggedIsSmi(array_size), &smi_size, &call_runtime);
526
527 BIND(&smi_size);
528
529 if (IsFastPackedElementsKind(elements_kind)) {
530 Label abort(this, Label::kDeferred);
531 Branch(SmiEqual(CAST(array_size), SmiConstant(0)), &small_smi_size, &abort);
532
533 BIND(&abort);
534 Node* reason = SmiConstant(AbortReason::kAllocatingNonEmptyPackedArray);
535 TailCallRuntime(Runtime::kAbort, context, reason);
536 } else {
537 int element_size =
538 IsDoubleElementsKind(elements_kind) ? kDoubleSize : kPointerSize;
539 int max_fast_elements =
540 (kMaxRegularHeapObjectSize - FixedArray::kHeaderSize - JSArray::kSize -
541 AllocationMemento::kSize) /
542 element_size;
543 Branch(SmiAboveOrEqual(CAST(array_size), SmiConstant(max_fast_elements)),
544 &call_runtime, &small_smi_size);
545 }
546
547 BIND(&small_smi_size);
548 {
549 Node* array = AllocateJSArray(
550 elements_kind, array_map, array_size, array_size,
551 mode == DONT_TRACK_ALLOCATION_SITE ? nullptr : allocation_site,
552 CodeStubAssembler::SMI_PARAMETERS);
553 Return(array);
554 }
555
556 BIND(&call_runtime);
557 {
558 TailCallRuntime(Runtime::kNewArray, context, array_function, array_size,
559 array_function, allocation_site);
560 }
561 }
562
TF_STUB(ArraySingleArgumentConstructorStub,ArrayConstructorAssembler)563 TF_STUB(ArraySingleArgumentConstructorStub, ArrayConstructorAssembler) {
564 ElementsKind elements_kind = stub->elements_kind();
565 Node* context = Parameter(Descriptor::kContext);
566 Node* function = Parameter(Descriptor::kFunction);
567 Node* native_context = LoadObjectField(function, JSFunction::kContextOffset);
568 Node* array_map = LoadJSArrayElementsMap(elements_kind, native_context);
569 AllocationSiteMode mode = DONT_TRACK_ALLOCATION_SITE;
570 if (stub->override_mode() == DONT_OVERRIDE) {
571 mode = AllocationSite::ShouldTrack(elements_kind)
572 ? TRACK_ALLOCATION_SITE
573 : DONT_TRACK_ALLOCATION_SITE;
574 }
575
576 Node* array_size = Parameter(Descriptor::kArraySizeSmiParameter);
577 Node* allocation_site = Parameter(Descriptor::kAllocationSite);
578
579 GenerateConstructor(context, function, array_map, array_size, allocation_site,
580 elements_kind, mode);
581 }
582
TF_STUB(InternalArraySingleArgumentConstructorStub,ArrayConstructorAssembler)583 TF_STUB(InternalArraySingleArgumentConstructorStub, ArrayConstructorAssembler) {
584 Node* context = Parameter(Descriptor::kContext);
585 Node* function = Parameter(Descriptor::kFunction);
586 Node* array_map =
587 LoadObjectField(function, JSFunction::kPrototypeOrInitialMapOffset);
588 Node* array_size = Parameter(Descriptor::kArraySizeSmiParameter);
589 Node* allocation_site = UndefinedConstant();
590
591 GenerateConstructor(context, function, array_map, array_size, allocation_site,
592 stub->elements_kind(), DONT_TRACK_ALLOCATION_SITE);
593 }
594
ArrayConstructorStub(Isolate * isolate)595 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
596 : PlatformCodeStub(isolate) {}
597
InternalArrayConstructorStub(Isolate * isolate)598 InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate)
599 : PlatformCodeStub(isolate) {}
600
CommonArrayConstructorStub(Isolate * isolate,ElementsKind kind,AllocationSiteOverrideMode override_mode)601 CommonArrayConstructorStub::CommonArrayConstructorStub(
602 Isolate* isolate, ElementsKind kind,
603 AllocationSiteOverrideMode override_mode)
604 : TurboFanCodeStub(isolate) {
605 // It only makes sense to override local allocation site behavior
606 // if there is a difference between the global allocation site policy
607 // for an ElementsKind and the desired usage of the stub.
608 DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
609 AllocationSite::ShouldTrack(kind));
610 set_sub_minor_key(ElementsKindBits::encode(kind) |
611 AllocationSiteOverrideModeBits::encode(override_mode));
612 }
613
614 } // namespace internal
615 } // namespace v8
616