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.
5 #include "src/code-stubs.h"
9 #include "src/bootstrapper.h"
10 #include "src/cpu-profiler.h"
11 #include "src/factory.h"
12 #include "src/gdb-jit.h"
13 #include "src/ic/handler-compiler.h"
14 #include "src/ic/ic.h"
15 #include "src/macro-assembler.h"
16 #include "src/parser.h"
22 RUNTIME_FUNCTION(UnexpectedStubMiss) {
23 FATAL("Unexpected deopt of a stub");
24 return Smi::FromInt(0);
28 CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
29 : call_descriptor_(stub->GetCallInterfaceDescriptor()),
30 stack_parameter_count_(no_reg),
31 hint_stack_parameter_count_(-1),
32 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
33 deoptimization_handler_(NULL),
35 has_miss_handler_(false) {
36 stub->InitializeDescriptor(this);
40 CodeStubDescriptor::CodeStubDescriptor(Isolate* isolate, uint32_t stub_key)
41 : stack_parameter_count_(no_reg),
42 hint_stack_parameter_count_(-1),
43 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
44 deoptimization_handler_(NULL),
46 has_miss_handler_(false) {
47 CodeStub::InitializeDescriptor(isolate, stub_key, this);
51 void CodeStubDescriptor::Initialize(Address deoptimization_handler,
52 int hint_stack_parameter_count,
53 StubFunctionMode function_mode) {
54 deoptimization_handler_ = deoptimization_handler;
55 hint_stack_parameter_count_ = hint_stack_parameter_count;
56 function_mode_ = function_mode;
60 void CodeStubDescriptor::Initialize(Register stack_parameter_count,
61 Address deoptimization_handler,
62 int hint_stack_parameter_count,
63 StubFunctionMode function_mode) {
64 Initialize(deoptimization_handler, hint_stack_parameter_count, function_mode);
65 stack_parameter_count_ = stack_parameter_count;
69 bool CodeStub::FindCodeInCache(Code** code_out) {
70 UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
71 int index = stubs->FindEntry(GetKey());
72 if (index != UnseededNumberDictionary::kNotFound) {
73 *code_out = Code::cast(stubs->ValueAt(index));
80 void CodeStub::RecordCodeGeneration(Handle<Code> code) {
81 std::ostringstream os;
84 CodeCreateEvent(Logger::STUB_TAG, *code, os.str().c_str()));
85 Counters* counters = isolate()->counters();
86 counters->total_stubs_code_size()->Increment(code->instruction_size());
88 code->VerifyEmbeddedObjects();
93 Code::Kind CodeStub::GetCodeKind() const {
98 Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) {
99 Handle<Code> ic = GetCode();
100 ic = isolate()->factory()->CopyCode(ic);
101 ic->FindAndReplace(pattern);
102 RecordCodeGeneration(ic);
107 Handle<Code> PlatformCodeStub::GenerateCode() {
108 Factory* factory = isolate()->factory();
110 // Generate the new code.
111 MacroAssembler masm(isolate(), NULL, 256);
114 // Update the static counter each time a new code stub is generated.
115 isolate()->counters()->code_stubs()->Increment();
117 // Generate the code for the stub.
118 masm.set_generating_stub(true);
119 // TODO(yangguo): remove this once we can serialize IC stubs.
120 masm.enable_serializer();
121 NoCurrentFrameScope scope(&masm);
125 // Create the code object.
128 // Copy the generated code into a heap object.
129 Code::Flags flags = Code::ComputeFlags(
134 Handle<Code> new_object = factory->NewCode(
135 desc, flags, masm.CodeObject(), NeedsImmovableCode());
140 Handle<Code> CodeStub::GetCode() {
141 Heap* heap = isolate()->heap();
143 if (UseSpecialCache() ? FindCodeInSpecialCache(&code)
144 : FindCodeInCache(&code)) {
145 DCHECK(GetCodeKind() == code->kind());
146 return Handle<Code>(code);
150 HandleScope scope(isolate());
152 Handle<Code> new_object = GenerateCode();
153 new_object->set_stub_key(GetKey());
154 FinishCode(new_object);
155 RecordCodeGeneration(new_object);
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;
163 new_object->Disassemble(name.str().c_str(), os);
168 if (UseSpecialCache()) {
169 AddToSpecialCache(new_object);
171 // Update the dictionary and the root in Heap.
172 Handle<UnseededNumberDictionary> dict =
173 UnseededNumberDictionary::AtNumberPut(
174 Handle<UnseededNumberDictionary>(heap->code_stubs()),
177 heap->SetRootCodeStubs(*dict);
183 DCHECK(!NeedsImmovableCode() ||
184 heap->lo_space()->Contains(code) ||
185 heap->code_space()->FirstPage()->Contains(code->address()));
186 return Handle<Code>(code, isolate());
190 const char* CodeStub::MajorName(CodeStub::Major major_key) {
192 #define DEF_CASE(name) case name: return #name "Stub";
193 CODE_STUB_LIST(DEF_CASE)
196 return "<NoCache>Stub";
205 void CodeStub::PrintBaseName(std::ostream& os) const { // NOLINT
206 os << MajorName(MajorKey());
210 void CodeStub::PrintName(std::ostream& os) const { // NOLINT
216 void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
217 DispatchedCall call) {
218 switch (MajorKeyFromKey(key)) {
219 #define DEF_CASE(NAME) \
221 NAME##Stub stub(key, isolate); \
222 CodeStub* pstub = &stub; \
223 call(pstub, value_out); \
226 CODE_STUB_LIST(DEF_CASE)
236 static void InitializeDescriptorDispatchedCall(CodeStub* stub,
238 CodeStubDescriptor* descriptor_out =
239 reinterpret_cast<CodeStubDescriptor*>(value_out);
240 stub->InitializeDescriptor(descriptor_out);
241 descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
245 void CodeStub::InitializeDescriptor(Isolate* isolate, uint32_t key,
246 CodeStubDescriptor* desc) {
247 void** value_out = reinterpret_cast<void**>(desc);
248 Dispatch(isolate, key, value_out, &InitializeDescriptorDispatchedCall);
252 void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
253 Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
254 // Code stubs with special cache cannot be recreated from stub key.
255 *code_out = stub->UseSpecialCache() ? Handle<Code>() : stub->GetCode();
259 MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
260 HandleScope scope(isolate);
262 void** value_out = reinterpret_cast<void**>(&code);
263 Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
264 return scope.CloseAndEscape(code);
269 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
270 // Generate the uninitialized versions of the stub.
271 for (int op = Token::BIT_OR; op <= Token::MOD; ++op) {
272 BinaryOpICStub stub(isolate, static_cast<Token::Value>(op), Strength::WEAK);
276 // Generate special versions of the stub.
277 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
281 void BinaryOpICStub::PrintState(std::ostream& os) const { // NOLINT
287 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
288 const BinaryOpICState& state) {
289 BinaryOpICStub stub(isolate, state);
295 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
296 // Generate special versions of the stub.
297 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
301 void BinaryOpICWithAllocationSiteStub::PrintState(
302 std::ostream& os) const { // NOLINT
308 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
309 Isolate* isolate, const BinaryOpICState& state) {
310 if (state.CouldCreateAllocationMementos()) {
311 BinaryOpICWithAllocationSiteStub stub(isolate, state);
317 std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags) {
319 case STRING_ADD_CHECK_NONE:
320 return os << "CheckNone";
321 case STRING_ADD_CHECK_LEFT:
322 return os << "CheckLeft";
323 case STRING_ADD_CHECK_RIGHT:
324 return os << "CheckRight";
325 case STRING_ADD_CHECK_BOTH:
326 return os << "CheckBoth";
333 void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT
334 os << "StringAddStub_" << flags() << "_" << pretenure_flag();
338 void StringAddTFStub::PrintBaseName(std::ostream& os) const { // NOLINT
339 os << "StringAddTFStub_" << flags() << "_" << pretenure_flag();
343 InlineCacheState CompareICStub::GetICState() const {
344 CompareICState::State state = Max(left(), right());
346 case CompareICState::UNINITIALIZED:
347 return ::v8::internal::UNINITIALIZED;
348 case CompareICState::SMI:
349 case CompareICState::NUMBER:
350 case CompareICState::INTERNALIZED_STRING:
351 case CompareICState::STRING:
352 case CompareICState::UNIQUE_NAME:
353 case CompareICState::OBJECT:
354 case CompareICState::KNOWN_OBJECT:
356 case CompareICState::GENERIC:
357 return ::v8::internal::GENERIC;
360 return ::v8::internal::UNINITIALIZED;
364 Condition CompareICStub::GetCondition() const {
365 return CompareIC::ComputeCondition(op());
369 void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
370 DCHECK(*known_map_ != NULL);
371 Isolate* isolate = new_object->GetIsolate();
372 Factory* factory = isolate->factory();
373 return Map::UpdateCodeCache(known_map_,
375 factory->strict_compare_ic_string() :
376 factory->compare_ic_string(),
381 bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
382 Factory* factory = isolate()->factory();
383 Code::Flags flags = Code::ComputeFlags(
386 DCHECK(op() == Token::EQ || op() == Token::EQ_STRICT);
387 Handle<Object> probe(
388 known_map_->FindInCodeCache(
390 *factory->strict_compare_ic_string() :
391 *factory->compare_ic_string(),
394 if (probe->IsCode()) {
395 *code_out = Code::cast(*probe);
397 CompareICStub decode((*code_out)->stub_key(), isolate());
398 DCHECK(op() == decode.op());
399 DCHECK(left() == decode.left());
400 DCHECK(right() == decode.right());
401 DCHECK(state() == decode.state());
409 void CompareICStub::Generate(MacroAssembler* masm) {
411 case CompareICState::UNINITIALIZED:
414 case CompareICState::SMI:
417 case CompareICState::NUMBER:
418 GenerateNumbers(masm);
420 case CompareICState::STRING:
421 GenerateStrings(masm);
423 case CompareICState::INTERNALIZED_STRING:
424 GenerateInternalizedStrings(masm);
426 case CompareICState::UNIQUE_NAME:
427 GenerateUniqueNames(masm);
429 case CompareICState::OBJECT:
430 GenerateObjects(masm);
432 case CompareICState::KNOWN_OBJECT:
433 DCHECK(*known_map_ != NULL);
434 GenerateKnownObjects(masm);
436 case CompareICState::GENERIC:
437 GenerateGeneric(masm);
443 void CompareNilICStub::UpdateStatus(Handle<Object> object) {
444 State state = this->state();
445 DCHECK(!state.Contains(GENERIC));
446 State old_state = state;
447 if (object->IsNull()) {
448 state.Add(NULL_TYPE);
449 } else if (object->IsUndefined()) {
450 state.Add(UNDEFINED);
451 } else if (object->IsUndetectableObject() ||
452 object->IsOddball() ||
453 !object->IsHeapObject()) {
456 } else if (IsMonomorphic()) {
460 state.Add(MONOMORPHIC_MAP);
462 TraceTransition(old_state, state);
463 set_sub_minor_key(TypesBits::update(sub_minor_key(), state.ToIntegral()));
469 Handle<JSFunction> GetFunction(Isolate* isolate, const char* name) {
470 v8::ExtensionConfiguration no_extensions;
471 MaybeHandle<Object> fun = Object::GetProperty(
472 isolate, isolate->factory()->code_stub_exports_object(), name);
473 Handle<JSFunction> function = Handle<JSFunction>::cast(fun.ToHandleChecked());
474 DCHECK(!function->IsUndefined() &&
475 "JavaScript implementation of stub not found");
481 Handle<Code> TurboFanCodeStub::GenerateCode() {
482 // Get the outer ("stub generator") function.
483 const char* name = CodeStub::MajorName(MajorKey());
484 Handle<JSFunction> outer = GetFunction(isolate(), name);
485 DCHECK_EQ(2, outer->shared()->length());
487 // Invoke the outer function to get the stub itself.
488 Factory* factory = isolate()->factory();
489 Handle<Object> call_conv = factory->InternalizeUtf8String(name);
490 Handle<Object> minor_key = factory->NewNumber(MinorKey());
491 Handle<Object> args[] = {call_conv, minor_key};
492 MaybeHandle<Object> result =
493 Execution::Call(isolate(), outer, factory->undefined_value(), 2, args);
494 Handle<JSFunction> inner = Handle<JSFunction>::cast(result.ToHandleChecked());
495 // Just to make sure nobody calls this...
496 inner->set_code(isolate()->builtins()->builtin(Builtins::kIllegal));
498 return Compiler::GetStubCode(inner, this).ToHandleChecked();
502 template<class StateType>
503 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
504 // Note: Although a no-op transition is semantically OK, it is hinting at a
505 // bug somewhere in our state transition machinery.
507 if (!FLAG_trace_ic) return;
511 os << ": " << from << "=>" << to << "]" << std::endl;
515 void CompareNilICStub::PrintBaseName(std::ostream& os) const { // NOLINT
516 CodeStub::PrintBaseName(os);
517 os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
521 void CompareNilICStub::PrintState(std::ostream& os) const { // NOLINT
526 // TODO(svenpanne) Make this a real infix_ostream_iterator.
527 class SimpleListPrinter {
529 explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {}
531 void Add(const char* s) {
546 std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s) {
548 SimpleListPrinter p(os);
549 if (s.IsEmpty()) p.Add("None");
550 if (s.Contains(CompareNilICStub::UNDEFINED)) p.Add("Undefined");
551 if (s.Contains(CompareNilICStub::NULL_TYPE)) p.Add("Null");
552 if (s.Contains(CompareNilICStub::MONOMORPHIC_MAP)) p.Add("MonomorphicMap");
553 if (s.Contains(CompareNilICStub::GENERIC)) p.Add("Generic");
558 Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
559 State state = this->state();
560 if (state.Contains(CompareNilICStub::GENERIC)) return Type::Any(zone);
562 Type* result = Type::None(zone);
563 if (state.Contains(CompareNilICStub::UNDEFINED)) {
564 result = Type::Union(result, Type::Undefined(zone), zone);
566 if (state.Contains(CompareNilICStub::NULL_TYPE)) {
567 result = Type::Union(result, Type::Null(zone), zone);
569 if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
571 map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
572 result = Type::Union(result, type, zone);
579 Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
580 Type* output_type = GetType(zone, map);
582 nil_value() == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
583 return Type::Union(output_type, nil_type, zone);
587 void CallICStub::PrintState(std::ostream& os) const { // NOLINT
592 void JSEntryStub::FinishCode(Handle<Code> code) {
593 Handle<FixedArray> handler_table =
594 code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
595 handler_table->set(0, Smi::FromInt(handler_offset_));
596 code->set_handler_table(*handler_table);
600 void LoadDictionaryElementStub::InitializeDescriptor(
601 CodeStubDescriptor* descriptor) {
602 descriptor->Initialize(
603 FUNCTION_ADDR(Runtime_KeyedLoadIC_MissFromStubFailure));
607 void KeyedLoadGenericStub::InitializeDescriptor(
608 CodeStubDescriptor* descriptor) {
609 descriptor->Initialize(
610 Runtime::FunctionForId(is_strong(language_mode())
611 ? Runtime::kKeyedGetPropertyStrong
612 : Runtime::kKeyedGetProperty)->entry);
616 void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
617 if (kind() == Code::STORE_IC) {
618 descriptor->Initialize(FUNCTION_ADDR(Runtime_StoreIC_MissFromStubFailure));
619 } else if (kind() == Code::KEYED_LOAD_IC) {
620 descriptor->Initialize(
621 FUNCTION_ADDR(Runtime_KeyedLoadIC_MissFromStubFailure));
622 } else if (kind() == Code::KEYED_STORE_IC) {
623 descriptor->Initialize(
624 FUNCTION_ADDR(Runtime_KeyedStoreIC_MissFromStubFailure));
629 CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() const {
630 if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
631 return LoadWithVectorDescriptor(isolate());
633 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC);
634 return FLAG_vector_stores ? VectorStoreICDescriptor(isolate())
635 : StoreDescriptor(isolate());
640 void StoreFastElementStub::InitializeDescriptor(
641 CodeStubDescriptor* descriptor) {
642 descriptor->Initialize(
643 FUNCTION_ADDR(Runtime_KeyedStoreIC_MissFromStubFailure));
647 void ElementsTransitionAndStoreStub::InitializeDescriptor(
648 CodeStubDescriptor* descriptor) {
649 descriptor->Initialize(
650 FUNCTION_ADDR(Runtime_ElementsTransitionAndStoreIC_Miss));
654 void ToObjectStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
655 descriptor->Initialize(Runtime::FunctionForId(Runtime::kToObject)->entry);
659 CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor()
661 if (FLAG_vector_stores) {
662 return VectorStoreTransitionDescriptor(isolate());
664 return StoreTransitionDescriptor(isolate());
668 CallInterfaceDescriptor
669 ElementsTransitionAndStoreStub::GetCallInterfaceDescriptor() const {
670 if (FLAG_vector_stores) {
671 return VectorStoreTransitionDescriptor(isolate());
673 return StoreTransitionDescriptor(isolate());
677 void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
678 descriptor->Initialize(Runtime::FunctionForId(Runtime::kNewClosure)->entry);
682 void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
685 void TypeofStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {}
688 void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
689 NumberToStringDescriptor call_descriptor(isolate());
690 descriptor->Initialize(
691 Runtime::FunctionForId(Runtime::kNumberToString)->entry);
695 void FastCloneShallowArrayStub::InitializeDescriptor(
696 CodeStubDescriptor* descriptor) {
697 FastCloneShallowArrayDescriptor call_descriptor(isolate());
698 descriptor->Initialize(
699 Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
703 void FastCloneShallowObjectStub::InitializeDescriptor(
704 CodeStubDescriptor* descriptor) {
705 FastCloneShallowObjectDescriptor call_descriptor(isolate());
706 descriptor->Initialize(
707 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
711 void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
714 void CreateWeakCellStub::InitializeDescriptor(CodeStubDescriptor* d) {}
717 void RegExpConstructResultStub::InitializeDescriptor(
718 CodeStubDescriptor* descriptor) {
719 descriptor->Initialize(
720 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry);
724 void TransitionElementsKindStub::InitializeDescriptor(
725 CodeStubDescriptor* descriptor) {
726 descriptor->Initialize(
727 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
731 void AllocateHeapNumberStub::InitializeDescriptor(
732 CodeStubDescriptor* descriptor) {
733 descriptor->Initialize(
734 Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry);
738 void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
739 descriptor->Initialize(FUNCTION_ADDR(Runtime_CompareNilIC_Miss));
740 descriptor->SetMissHandler(ExternalReference(
741 Runtime::FunctionForId(Runtime::kCompareNilIC_Miss), isolate()));
745 void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
746 descriptor->Initialize(FUNCTION_ADDR(Runtime_ToBooleanIC_Miss));
747 descriptor->SetMissHandler(ExternalReference(
748 Runtime::FunctionForId(Runtime::kToBooleanIC_Miss), isolate()));
752 void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
753 descriptor->Initialize(FUNCTION_ADDR(Runtime_BinaryOpIC_Miss));
754 descriptor->SetMissHandler(ExternalReference(
755 Runtime::FunctionForId(Runtime::kBinaryOpIC_Miss), isolate()));
759 void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
760 CodeStubDescriptor* descriptor) {
761 descriptor->Initialize(
762 FUNCTION_ADDR(Runtime_BinaryOpIC_MissWithAllocationSite));
766 void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
767 descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAdd)->entry);
771 void GrowArrayElementsStub::InitializeDescriptor(
772 CodeStubDescriptor* descriptor) {
773 descriptor->Initialize(
774 Runtime::FunctionForId(Runtime::kGrowArrayElements)->entry);
778 void TypeofStub::GenerateAheadOfTime(Isolate* isolate) {
779 TypeofStub stub(isolate);
784 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
785 CreateAllocationSiteStub stub(isolate);
790 void CreateWeakCellStub::GenerateAheadOfTime(Isolate* isolate) {
791 CreateWeakCellStub stub(isolate);
796 void StoreElementStub::Generate(MacroAssembler* masm) {
797 switch (elements_kind()) {
799 case FAST_HOLEY_ELEMENTS:
800 case FAST_SMI_ELEMENTS:
801 case FAST_HOLEY_SMI_ELEMENTS:
802 case FAST_DOUBLE_ELEMENTS:
803 case FAST_HOLEY_DOUBLE_ELEMENTS:
804 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
805 case TYPE##_ELEMENTS:
807 TYPED_ARRAYS(TYPED_ARRAY_CASE)
808 #undef TYPED_ARRAY_CASE
811 case DICTIONARY_ELEMENTS:
812 ElementHandlerCompiler::GenerateStoreSlow(masm);
814 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
815 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
823 void StoreFastElementStub::GenerateAheadOfTime(Isolate* isolate) {
824 StoreFastElementStub(isolate, false, FAST_HOLEY_ELEMENTS, STANDARD_STORE)
826 StoreFastElementStub(isolate, false, FAST_HOLEY_ELEMENTS,
827 STORE_AND_GROW_NO_TRANSITION).GetCode();
828 for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
829 ElementsKind kind = static_cast<ElementsKind>(i);
830 StoreFastElementStub(isolate, true, kind, STANDARD_STORE).GetCode();
831 StoreFastElementStub(isolate, true, kind, STORE_AND_GROW_NO_TRANSITION)
837 void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
840 GenerateReadElement(masm);
842 case NEW_SLOPPY_FAST:
843 GenerateNewSloppyFast(masm);
845 case NEW_SLOPPY_SLOW:
846 GenerateNewSloppySlow(masm);
849 GenerateNewStrict(masm);
855 void ArgumentsAccessStub::PrintName(std::ostream& os) const { // NOLINT
856 os << "ArgumentsAccessStub_";
861 case NEW_SLOPPY_FAST:
862 os << "NewSloppyFast";
864 case NEW_SLOPPY_SLOW:
865 os << "NewSloppySlow";
875 void CallFunctionStub::PrintName(std::ostream& os) const { // NOLINT
876 os << "CallFunctionStub_Args" << argc();
880 void CallConstructStub::PrintName(std::ostream& os) const { // NOLINT
881 os << "CallConstructStub";
882 if (RecordCallTarget()) os << "_Recording";
886 void ArrayConstructorStub::PrintName(std::ostream& os) const { // NOLINT
887 os << "ArrayConstructorStub";
888 switch (argument_count()) {
899 os << "_More_Than_One";
906 std::ostream& ArrayConstructorStubBase::BasePrintName(
907 std::ostream& os, // NOLINT
908 const char* name) const {
909 os << name << "_" << ElementsKindToString(elements_kind());
910 if (override_mode() == DISABLE_ALLOCATION_SITES) {
911 os << "_DISABLE_ALLOCATION_SITES";
917 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
918 Types new_types = types();
919 Types old_types = new_types;
920 bool to_boolean_value = new_types.UpdateStatus(object);
921 TraceTransition(old_types, new_types);
922 set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToIntegral()));
923 return to_boolean_value;
927 void ToBooleanStub::PrintState(std::ostream& os) const { // NOLINT
932 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) {
934 SimpleListPrinter p(os);
935 if (s.IsEmpty()) p.Add("None");
936 if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined");
937 if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool");
938 if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null");
939 if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi");
940 if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject");
941 if (s.Contains(ToBooleanStub::STRING)) p.Add("String");
942 if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol");
943 if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber");
944 if (s.Contains(ToBooleanStub::SIMD_VALUE)) p.Add("SimdValue");
949 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
950 if (object->IsUndefined()) {
953 } else if (object->IsBoolean()) {
955 return object->IsTrue();
956 } else if (object->IsNull()) {
959 } else if (object->IsSmi()) {
961 return Smi::cast(*object)->value() != 0;
962 } else if (object->IsSpecObject()) {
964 return !object->IsUndetectableObject();
965 } else if (object->IsString()) {
967 return !object->IsUndetectableObject() &&
968 String::cast(*object)->length() != 0;
969 } else if (object->IsSymbol()) {
972 } else if (object->IsHeapNumber()) {
973 DCHECK(!object->IsUndetectableObject());
975 double value = HeapNumber::cast(*object)->value();
976 return value != 0 && !std::isnan(value);
977 } else if (object->IsSimd128Value()) {
981 // We should never see an internal object at runtime here!
988 bool ToBooleanStub::Types::NeedsMap() const {
989 return Contains(ToBooleanStub::SPEC_OBJECT) ||
990 Contains(ToBooleanStub::STRING) || Contains(ToBooleanStub::SYMBOL) ||
991 Contains(ToBooleanStub::HEAP_NUMBER) ||
992 Contains(ToBooleanStub::SIMD_VALUE);
996 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
997 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
998 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
1004 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
1005 intptr_t stack_pointer,
1007 FunctionEntryHook entry_hook = isolate->function_entry_hook();
1008 DCHECK(entry_hook != NULL);
1009 entry_hook(function, stack_pointer);
1013 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
1014 : PlatformCodeStub(isolate) {
1015 minor_key_ = ArgumentCountBits::encode(ANY);
1016 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1020 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
1022 : PlatformCodeStub(isolate) {
1023 if (argument_count == 0) {
1024 minor_key_ = ArgumentCountBits::encode(NONE);
1025 } else if (argument_count == 1) {
1026 minor_key_ = ArgumentCountBits::encode(ONE);
1027 } else if (argument_count >= 2) {
1028 minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
1032 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1036 InternalArrayConstructorStub::InternalArrayConstructorStub(
1037 Isolate* isolate) : PlatformCodeStub(isolate) {
1038 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1042 Representation RepresentationFromType(Type* type) {
1043 if (type->Is(Type::UntaggedSigned()) || type->Is(Type::UntaggedUnsigned())) {
1044 return Representation::Integer32();
1047 if (type->Is(Type::TaggedSigned())) {
1048 return Representation::Smi();
1051 if (type->Is(Type::UntaggedPointer())) {
1052 return Representation::External();
1055 DCHECK(!type->Is(Type::Untagged()));
1056 return Representation::Tagged();
1058 } // namespace internal