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"
21 CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
22 : call_descriptor_(stub->GetCallInterfaceDescriptor()),
23 stack_parameter_count_(no_reg),
24 hint_stack_parameter_count_(-1),
25 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
26 deoptimization_handler_(NULL),
27 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
29 has_miss_handler_(false) {
30 stub->InitializeDescriptor(this);
34 CodeStubDescriptor::CodeStubDescriptor(Isolate* isolate, uint32_t stub_key)
35 : stack_parameter_count_(no_reg),
36 hint_stack_parameter_count_(-1),
37 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
38 deoptimization_handler_(NULL),
39 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
41 has_miss_handler_(false) {
42 CodeStub::InitializeDescriptor(isolate, stub_key, this);
46 void CodeStubDescriptor::Initialize(Address deoptimization_handler,
47 int hint_stack_parameter_count,
48 StubFunctionMode function_mode) {
49 deoptimization_handler_ = deoptimization_handler;
50 hint_stack_parameter_count_ = hint_stack_parameter_count;
51 function_mode_ = function_mode;
55 void CodeStubDescriptor::Initialize(Register stack_parameter_count,
56 Address deoptimization_handler,
57 int hint_stack_parameter_count,
58 StubFunctionMode function_mode,
59 HandlerArgumentsMode handler_mode) {
60 Initialize(deoptimization_handler, hint_stack_parameter_count, function_mode);
61 stack_parameter_count_ = stack_parameter_count;
62 handler_arguments_mode_ = handler_mode;
66 bool CodeStub::FindCodeInCache(Code** code_out) {
67 UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
68 int index = stubs->FindEntry(GetKey());
69 if (index != UnseededNumberDictionary::kNotFound) {
70 *code_out = Code::cast(stubs->ValueAt(index));
77 void CodeStub::RecordCodeGeneration(Handle<Code> code) {
78 std::ostringstream os;
81 CodeCreateEvent(Logger::STUB_TAG, *code, os.str().c_str()));
82 Counters* counters = isolate()->counters();
83 counters->total_stubs_code_size()->Increment(code->instruction_size());
85 code->VerifyEmbeddedObjects();
90 Code::Kind CodeStub::GetCodeKind() const {
95 Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) {
96 Handle<Code> ic = GetCode();
97 ic = isolate()->factory()->CopyCode(ic);
98 ic->FindAndReplace(pattern);
99 RecordCodeGeneration(ic);
104 Handle<Code> PlatformCodeStub::GenerateCode() {
105 Factory* factory = isolate()->factory();
107 // Generate the new code.
108 MacroAssembler masm(isolate(), NULL, 256);
111 // Update the static counter each time a new code stub is generated.
112 isolate()->counters()->code_stubs()->Increment();
114 // Generate the code for the stub.
115 masm.set_generating_stub(true);
116 // TODO(yangguo): remove this once we can serialize IC stubs.
117 masm.enable_serializer();
118 NoCurrentFrameScope scope(&masm);
122 // Create the code object.
126 // Copy the generated code into a heap object.
127 Code::Flags flags = Code::ComputeFlags(
132 Handle<Code> new_object = factory->NewCode(
133 desc, flags, masm.CodeObject(), NeedsImmovableCode());
138 Handle<Code> CodeStub::GetCode() {
139 Heap* heap = isolate()->heap();
141 if (UseSpecialCache() ? FindCodeInSpecialCache(&code)
142 : FindCodeInCache(&code)) {
143 DCHECK(GetCodeKind() == code->kind());
144 return Handle<Code>(code);
148 HandleScope scope(isolate());
150 Handle<Code> new_object = GenerateCode();
151 new_object->set_stub_key(GetKey());
152 FinishCode(new_object);
153 RecordCodeGeneration(new_object);
155 #ifdef ENABLE_DISASSEMBLER
156 if (FLAG_print_code_stubs) {
157 CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
158 OFStream os(trace_scope.file());
159 std::ostringstream name;
161 new_object->Disassemble(name.str().c_str(), os);
166 if (UseSpecialCache()) {
167 AddToSpecialCache(new_object);
169 // Update the dictionary and the root in Heap.
170 Handle<UnseededNumberDictionary> dict =
171 UnseededNumberDictionary::AtNumberPut(
172 Handle<UnseededNumberDictionary>(heap->code_stubs()),
175 heap->public_set_code_stubs(*dict);
181 DCHECK(!NeedsImmovableCode() ||
182 heap->lo_space()->Contains(code) ||
183 heap->code_space()->FirstPage()->Contains(code->address()));
184 return Handle<Code>(code, isolate());
188 const char* CodeStub::MajorName(CodeStub::Major major_key,
189 bool allow_unknown_keys) {
191 #define DEF_CASE(name) case name: return #name "Stub";
192 CODE_STUB_LIST(DEF_CASE)
195 return "<NoCache>Stub";
204 void CodeStub::PrintBaseName(std::ostream& os) const { // NOLINT
205 os << MajorName(MajorKey(), false);
209 void CodeStub::PrintName(std::ostream& os) const { // NOLINT
215 void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
216 DispatchedCall call) {
217 switch (MajorKeyFromKey(key)) {
218 #define DEF_CASE(NAME) \
220 NAME##Stub stub(key, isolate); \
221 CodeStub* pstub = &stub; \
222 call(pstub, value_out); \
225 CODE_STUB_LIST(DEF_CASE)
235 static void InitializeDescriptorDispatchedCall(CodeStub* stub,
237 CodeStubDescriptor* descriptor_out =
238 reinterpret_cast<CodeStubDescriptor*>(value_out);
239 stub->InitializeDescriptor(descriptor_out);
240 descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
244 void CodeStub::InitializeDescriptor(Isolate* isolate, uint32_t key,
245 CodeStubDescriptor* desc) {
246 void** value_out = reinterpret_cast<void**>(desc);
247 Dispatch(isolate, key, value_out, &InitializeDescriptorDispatchedCall);
251 void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
252 Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
253 // Code stubs with special cache cannot be recreated from stub key.
254 *code_out = stub->UseSpecialCache() ? Handle<Code>() : stub->GetCode();
258 MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
259 HandleScope scope(isolate);
261 void** value_out = reinterpret_cast<void**>(&code);
262 Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
263 return scope.CloseAndEscape(code);
268 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
269 // Generate the uninitialized versions of the stub.
270 for (int op = Token::BIT_OR; op <= Token::MOD; ++op) {
271 BinaryOpICStub stub(isolate, static_cast<Token::Value>(op));
275 // Generate special versions of the stub.
276 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
280 void BinaryOpICStub::PrintState(std::ostream& os) const { // NOLINT
286 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
287 const BinaryOpICState& state) {
288 BinaryOpICStub stub(isolate, state);
294 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
295 // Generate special versions of the stub.
296 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
300 void BinaryOpICWithAllocationSiteStub::PrintState(
301 std::ostream& os) const { // NOLINT
307 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
308 Isolate* isolate, const BinaryOpICState& state) {
309 if (state.CouldCreateAllocationMementos()) {
310 BinaryOpICWithAllocationSiteStub stub(isolate, state);
316 void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT
317 os << "StringAddStub";
318 if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
320 } else if ((flags() & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
322 } else if ((flags() & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
325 if (pretenure_flag() == TENURED) {
331 InlineCacheState CompareICStub::GetICState() const {
332 CompareICState::State state = Max(left(), right());
334 case CompareICState::UNINITIALIZED:
335 return ::v8::internal::UNINITIALIZED;
336 case CompareICState::SMI:
337 case CompareICState::NUMBER:
338 case CompareICState::INTERNALIZED_STRING:
339 case CompareICState::STRING:
340 case CompareICState::UNIQUE_NAME:
341 case CompareICState::OBJECT:
342 case CompareICState::KNOWN_OBJECT:
344 case CompareICState::GENERIC:
345 return ::v8::internal::GENERIC;
348 return ::v8::internal::UNINITIALIZED;
352 Condition CompareICStub::GetCondition() const {
353 return CompareIC::ComputeCondition(op());
357 void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
358 DCHECK(*known_map_ != NULL);
359 Isolate* isolate = new_object->GetIsolate();
360 Factory* factory = isolate->factory();
361 return Map::UpdateCodeCache(known_map_,
363 factory->strict_compare_ic_string() :
364 factory->compare_ic_string(),
369 bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
370 Factory* factory = isolate()->factory();
371 Code::Flags flags = Code::ComputeFlags(
374 DCHECK(op() == Token::EQ || op() == Token::EQ_STRICT);
375 Handle<Object> probe(
376 known_map_->FindInCodeCache(
378 *factory->strict_compare_ic_string() :
379 *factory->compare_ic_string(),
382 if (probe->IsCode()) {
383 *code_out = Code::cast(*probe);
385 CompareICStub decode((*code_out)->stub_key(), isolate());
386 DCHECK(op() == decode.op());
387 DCHECK(left() == decode.left());
388 DCHECK(right() == decode.right());
389 DCHECK(state() == decode.state());
397 void CompareICStub::Generate(MacroAssembler* masm) {
399 case CompareICState::UNINITIALIZED:
402 case CompareICState::SMI:
405 case CompareICState::NUMBER:
406 GenerateNumbers(masm);
408 case CompareICState::STRING:
409 GenerateStrings(masm);
411 case CompareICState::INTERNALIZED_STRING:
412 GenerateInternalizedStrings(masm);
414 case CompareICState::UNIQUE_NAME:
415 GenerateUniqueNames(masm);
417 case CompareICState::OBJECT:
418 GenerateObjects(masm);
420 case CompareICState::KNOWN_OBJECT:
421 DCHECK(*known_map_ != NULL);
422 GenerateKnownObjects(masm);
424 case CompareICState::GENERIC:
425 GenerateGeneric(masm);
431 void CompareNilICStub::UpdateStatus(Handle<Object> object) {
432 State state = this->state();
433 DCHECK(!state.Contains(GENERIC));
434 State old_state = state;
435 if (object->IsNull()) {
436 state.Add(NULL_TYPE);
437 } else if (object->IsUndefined()) {
438 state.Add(UNDEFINED);
439 } else if (object->IsUndetectableObject() ||
440 object->IsOddball() ||
441 !object->IsHeapObject()) {
444 } else if (IsMonomorphic()) {
448 state.Add(MONOMORPHIC_MAP);
450 TraceTransition(old_state, state);
451 set_sub_minor_key(TypesBits::update(sub_minor_key(), state.ToIntegral()));
455 template<class StateType>
456 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
457 // Note: Although a no-op transition is semantically OK, it is hinting at a
458 // bug somewhere in our state transition machinery.
460 if (!FLAG_trace_ic) return;
464 os << ": " << from << "=>" << to << "]" << std::endl;
468 void CompareNilICStub::PrintBaseName(std::ostream& os) const { // NOLINT
469 CodeStub::PrintBaseName(os);
470 os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
474 void CompareNilICStub::PrintState(std::ostream& os) const { // NOLINT
479 // TODO(svenpanne) Make this a real infix_ostream_iterator.
480 class SimpleListPrinter {
482 explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {}
484 void Add(const char* s) {
499 std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s) {
501 SimpleListPrinter p(os);
502 if (s.IsEmpty()) p.Add("None");
503 if (s.Contains(CompareNilICStub::UNDEFINED)) p.Add("Undefined");
504 if (s.Contains(CompareNilICStub::NULL_TYPE)) p.Add("Null");
505 if (s.Contains(CompareNilICStub::MONOMORPHIC_MAP)) p.Add("MonomorphicMap");
506 if (s.Contains(CompareNilICStub::GENERIC)) p.Add("Generic");
511 Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
512 State state = this->state();
513 if (state.Contains(CompareNilICStub::GENERIC)) return Type::Any(zone);
515 Type* result = Type::None(zone);
516 if (state.Contains(CompareNilICStub::UNDEFINED)) {
517 result = Type::Union(result, Type::Undefined(zone), zone);
519 if (state.Contains(CompareNilICStub::NULL_TYPE)) {
520 result = Type::Union(result, Type::Null(zone), zone);
522 if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
524 map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
525 result = Type::Union(result, type, zone);
532 Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
533 Type* output_type = GetType(zone, map);
535 nil_value() == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
536 return Type::Union(output_type, nil_type, zone);
540 void CallIC_ArrayStub::PrintState(std::ostream& os) const { // NOLINT
541 os << state() << " (Array)";
545 void CallICStub::PrintState(std::ostream& os) const { // NOLINT
550 void InstanceofStub::PrintName(std::ostream& os) const { // NOLINT
551 os << "InstanceofStub";
552 if (HasArgsInRegisters()) os << "_REGS";
553 if (HasCallSiteInlineCheck()) os << "_INLINE";
554 if (ReturnTrueFalseObject()) os << "_TRUEFALSE";
558 void JSEntryStub::FinishCode(Handle<Code> code) {
559 Handle<FixedArray> handler_table =
560 code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
561 handler_table->set(0, Smi::FromInt(handler_offset_));
562 code->set_handler_table(*handler_table);
566 void LoadFastElementStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
567 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
571 void LoadDictionaryElementStub::InitializeDescriptor(
572 CodeStubDescriptor* descriptor) {
573 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
577 void KeyedLoadGenericStub::InitializeDescriptor(
578 CodeStubDescriptor* descriptor) {
579 descriptor->Initialize(
580 Runtime::FunctionForId(Runtime::kKeyedGetProperty)->entry);
584 void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
585 if (kind() == Code::STORE_IC) {
586 descriptor->Initialize(FUNCTION_ADDR(StoreIC_MissFromStubFailure));
587 } else if (kind() == Code::KEYED_LOAD_IC) {
588 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
593 CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() {
594 if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
595 if (FLAG_vector_ics) {
596 return VectorLoadICDescriptor(isolate());
598 return LoadDescriptor(isolate());
600 DCHECK_EQ(Code::STORE_IC, kind());
601 return StoreDescriptor(isolate());
606 void StoreFastElementStub::InitializeDescriptor(
607 CodeStubDescriptor* descriptor) {
608 descriptor->Initialize(FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
612 void ElementsTransitionAndStoreStub::InitializeDescriptor(
613 CodeStubDescriptor* descriptor) {
614 descriptor->Initialize(FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss));
618 CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor() {
619 return StoreTransitionDescriptor(isolate());
623 static void InitializeVectorLoadStub(Isolate* isolate,
624 CodeStubDescriptor* descriptor,
625 Address deoptimization_handler) {
626 DCHECK(FLAG_vector_ics);
627 descriptor->Initialize(deoptimization_handler);
631 void VectorLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
632 InitializeVectorLoadStub(isolate(), descriptor,
633 FUNCTION_ADDR(LoadIC_MissFromStubFailure));
637 void VectorKeyedLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
638 InitializeVectorLoadStub(isolate(), descriptor,
639 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
643 void MegamorphicLoadStub::InitializeDescriptor(CodeStubDescriptor* d) {}
646 void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
647 descriptor->Initialize(
648 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry);
652 void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
655 void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
656 NumberToStringDescriptor call_descriptor(isolate());
657 descriptor->Initialize(
658 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry);
662 void FastCloneShallowArrayStub::InitializeDescriptor(
663 CodeStubDescriptor* descriptor) {
664 FastCloneShallowArrayDescriptor call_descriptor(isolate());
665 descriptor->Initialize(
666 Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
670 void FastCloneShallowObjectStub::InitializeDescriptor(
671 CodeStubDescriptor* descriptor) {
672 FastCloneShallowObjectDescriptor call_descriptor(isolate());
673 descriptor->Initialize(
674 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
678 void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
681 void CreateWeakCellStub::InitializeDescriptor(CodeStubDescriptor* d) {}
684 void RegExpConstructResultStub::InitializeDescriptor(
685 CodeStubDescriptor* descriptor) {
686 descriptor->Initialize(
687 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry);
691 void TransitionElementsKindStub::InitializeDescriptor(
692 CodeStubDescriptor* descriptor) {
693 descriptor->Initialize(
694 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
698 void AllocateHeapNumberStub::InitializeDescriptor(
699 CodeStubDescriptor* descriptor) {
700 descriptor->Initialize(
701 Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry);
705 void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
706 descriptor->Initialize(FUNCTION_ADDR(CompareNilIC_Miss));
707 descriptor->SetMissHandler(
708 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate()));
712 void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
713 descriptor->Initialize(FUNCTION_ADDR(ToBooleanIC_Miss));
714 descriptor->SetMissHandler(
715 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate()));
719 void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
720 descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_Miss));
721 descriptor->SetMissHandler(
722 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate()));
726 void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
727 CodeStubDescriptor* descriptor) {
728 descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite));
732 void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
733 descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAdd)->entry);
737 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
738 CreateAllocationSiteStub stub(isolate);
743 void CreateWeakCellStub::GenerateAheadOfTime(Isolate* isolate) {
744 CreateWeakCellStub stub(isolate);
749 void StoreElementStub::Generate(MacroAssembler* masm) {
750 switch (elements_kind()) {
752 case FAST_HOLEY_ELEMENTS:
753 case FAST_SMI_ELEMENTS:
754 case FAST_HOLEY_SMI_ELEMENTS:
755 case FAST_DOUBLE_ELEMENTS:
756 case FAST_HOLEY_DOUBLE_ELEMENTS:
757 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
758 case EXTERNAL_##TYPE##_ELEMENTS: \
759 case TYPE##_ELEMENTS:
761 TYPED_ARRAYS(TYPED_ARRAY_CASE)
762 #undef TYPED_ARRAY_CASE
765 case DICTIONARY_ELEMENTS:
766 ElementHandlerCompiler::GenerateStoreSlow(masm);
768 case SLOPPY_ARGUMENTS_ELEMENTS:
775 void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
778 GenerateReadElement(masm);
780 case NEW_SLOPPY_FAST:
781 GenerateNewSloppyFast(masm);
783 case NEW_SLOPPY_SLOW:
784 GenerateNewSloppySlow(masm);
787 GenerateNewStrict(masm);
793 void RestParamAccessStub::Generate(MacroAssembler* masm) {
798 void ArgumentsAccessStub::PrintName(std::ostream& os) const { // NOLINT
799 os << "ArgumentsAccessStub_";
804 case NEW_SLOPPY_FAST:
805 os << "NewSloppyFast";
807 case NEW_SLOPPY_SLOW:
808 os << "NewSloppySlow";
818 void RestParamAccessStub::PrintName(std::ostream& os) const { // NOLINT
819 os << "RestParamAccessStub_";
823 void CallFunctionStub::PrintName(std::ostream& os) const { // NOLINT
824 os << "CallFunctionStub_Args" << argc();
828 void CallConstructStub::PrintName(std::ostream& os) const { // NOLINT
829 os << "CallConstructStub";
830 if (RecordCallTarget()) os << "_Recording";
834 void ArrayConstructorStub::PrintName(std::ostream& os) const { // NOLINT
835 os << "ArrayConstructorStub";
836 switch (argument_count()) {
847 os << "_More_Than_One";
854 std::ostream& ArrayConstructorStubBase::BasePrintName(
855 std::ostream& os, // NOLINT
856 const char* name) const {
857 os << name << "_" << ElementsKindToString(elements_kind());
858 if (override_mode() == DISABLE_ALLOCATION_SITES) {
859 os << "_DISABLE_ALLOCATION_SITES";
865 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
866 Types new_types = types();
867 Types old_types = new_types;
868 bool to_boolean_value = new_types.UpdateStatus(object);
869 TraceTransition(old_types, new_types);
870 set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToByte()));
871 return to_boolean_value;
875 void ToBooleanStub::PrintState(std::ostream& os) const { // NOLINT
880 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) {
882 SimpleListPrinter p(os);
883 if (s.IsEmpty()) p.Add("None");
884 if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined");
885 if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool");
886 if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null");
887 if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi");
888 if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject");
889 if (s.Contains(ToBooleanStub::STRING)) p.Add("String");
890 if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol");
891 if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber");
896 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
897 if (object->IsUndefined()) {
900 } else if (object->IsBoolean()) {
902 return object->IsTrue();
903 } else if (object->IsNull()) {
906 } else if (object->IsSmi()) {
908 return Smi::cast(*object)->value() != 0;
909 } else if (object->IsSpecObject()) {
911 return !object->IsUndetectableObject();
912 } else if (object->IsString()) {
914 return !object->IsUndetectableObject() &&
915 String::cast(*object)->length() != 0;
916 } else if (object->IsSymbol()) {
919 } else if (object->IsHeapNumber()) {
920 DCHECK(!object->IsUndetectableObject());
922 double value = HeapNumber::cast(*object)->value();
923 return value != 0 && !std::isnan(value);
925 // We should never see an internal object at runtime here!
932 bool ToBooleanStub::Types::NeedsMap() const {
933 return Contains(ToBooleanStub::SPEC_OBJECT)
934 || Contains(ToBooleanStub::STRING)
935 || Contains(ToBooleanStub::SYMBOL)
936 || Contains(ToBooleanStub::HEAP_NUMBER);
940 bool ToBooleanStub::Types::CanBeUndetectable() const {
941 return Contains(ToBooleanStub::SPEC_OBJECT)
942 || Contains(ToBooleanStub::STRING);
946 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
947 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
948 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
954 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
955 intptr_t stack_pointer,
957 FunctionEntryHook entry_hook = isolate->function_entry_hook();
958 DCHECK(entry_hook != NULL);
959 entry_hook(function, stack_pointer);
963 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
964 : PlatformCodeStub(isolate) {
965 minor_key_ = ArgumentCountBits::encode(ANY);
966 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
970 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
972 : PlatformCodeStub(isolate) {
973 if (argument_count == 0) {
974 minor_key_ = ArgumentCountBits::encode(NONE);
975 } else if (argument_count == 1) {
976 minor_key_ = ArgumentCountBits::encode(ONE);
977 } else if (argument_count >= 2) {
978 minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
982 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
986 InternalArrayConstructorStub::InternalArrayConstructorStub(
987 Isolate* isolate) : PlatformCodeStub(isolate) {
988 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
992 } } // namespace v8::internal