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),
34 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
36 has_miss_handler_(false) {
37 stub->InitializeDescriptor(this);
41 CodeStubDescriptor::CodeStubDescriptor(Isolate* isolate, uint32_t stub_key)
42 : stack_parameter_count_(no_reg),
43 hint_stack_parameter_count_(-1),
44 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
45 deoptimization_handler_(NULL),
46 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
48 has_miss_handler_(false) {
49 CodeStub::InitializeDescriptor(isolate, stub_key, this);
53 void CodeStubDescriptor::Initialize(Address deoptimization_handler,
54 int hint_stack_parameter_count,
55 StubFunctionMode function_mode) {
56 deoptimization_handler_ = deoptimization_handler;
57 hint_stack_parameter_count_ = hint_stack_parameter_count;
58 function_mode_ = function_mode;
62 void CodeStubDescriptor::Initialize(Register stack_parameter_count,
63 Address deoptimization_handler,
64 int hint_stack_parameter_count,
65 StubFunctionMode function_mode,
66 HandlerArgumentsMode handler_mode) {
67 Initialize(deoptimization_handler, hint_stack_parameter_count, function_mode);
68 stack_parameter_count_ = stack_parameter_count;
69 handler_arguments_mode_ = handler_mode;
73 bool CodeStub::FindCodeInCache(Code** code_out) {
74 UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
75 int index = stubs->FindEntry(GetKey());
76 if (index != UnseededNumberDictionary::kNotFound) {
77 *code_out = Code::cast(stubs->ValueAt(index));
84 void CodeStub::RecordCodeGeneration(Handle<Code> code) {
85 std::ostringstream os;
88 CodeCreateEvent(Logger::STUB_TAG, *code, os.str().c_str()));
89 Counters* counters = isolate()->counters();
90 counters->total_stubs_code_size()->Increment(code->instruction_size());
92 code->VerifyEmbeddedObjects();
97 Code::Kind CodeStub::GetCodeKind() const {
102 Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) {
103 Handle<Code> ic = GetCode();
104 ic = isolate()->factory()->CopyCode(ic);
105 ic->FindAndReplace(pattern);
106 RecordCodeGeneration(ic);
111 Handle<Code> PlatformCodeStub::GenerateCode() {
112 Factory* factory = isolate()->factory();
114 // Generate the new code.
115 MacroAssembler masm(isolate(), NULL, 256);
118 // Update the static counter each time a new code stub is generated.
119 isolate()->counters()->code_stubs()->Increment();
121 // Generate the code for the stub.
122 masm.set_generating_stub(true);
123 // TODO(yangguo): remove this once we can serialize IC stubs.
124 masm.enable_serializer();
125 NoCurrentFrameScope scope(&masm);
129 // Create the code object.
132 // Copy the generated code into a heap object.
133 Code::Flags flags = Code::ComputeFlags(
138 Handle<Code> new_object = factory->NewCode(
139 desc, flags, masm.CodeObject(), NeedsImmovableCode());
144 Handle<Code> CodeStub::GetCode() {
145 Heap* heap = isolate()->heap();
147 if (UseSpecialCache() ? FindCodeInSpecialCache(&code)
148 : FindCodeInCache(&code)) {
149 DCHECK(GetCodeKind() == code->kind());
150 return Handle<Code>(code);
154 HandleScope scope(isolate());
156 Handle<Code> new_object = GenerateCode();
157 new_object->set_stub_key(GetKey());
158 FinishCode(new_object);
159 RecordCodeGeneration(new_object);
161 #ifdef ENABLE_DISASSEMBLER
162 if (FLAG_print_code_stubs) {
163 CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
164 OFStream os(trace_scope.file());
165 std::ostringstream name;
167 new_object->Disassemble(name.str().c_str(), os);
172 if (UseSpecialCache()) {
173 AddToSpecialCache(new_object);
175 // Update the dictionary and the root in Heap.
176 Handle<UnseededNumberDictionary> dict =
177 UnseededNumberDictionary::AtNumberPut(
178 Handle<UnseededNumberDictionary>(heap->code_stubs()),
181 heap->public_set_code_stubs(*dict);
187 DCHECK(!NeedsImmovableCode() ||
188 heap->lo_space()->Contains(code) ||
189 heap->code_space()->FirstPage()->Contains(code->address()));
190 return Handle<Code>(code, isolate());
194 const char* CodeStub::MajorName(CodeStub::Major major_key,
195 bool allow_unknown_keys) {
197 #define DEF_CASE(name) case name: return #name "Stub";
198 CODE_STUB_LIST(DEF_CASE)
201 return "<NoCache>Stub";
210 void CodeStub::PrintBaseName(std::ostream& os) const { // NOLINT
211 os << MajorName(MajorKey(), false);
215 void CodeStub::PrintName(std::ostream& os) const { // NOLINT
221 void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
222 DispatchedCall call) {
223 switch (MajorKeyFromKey(key)) {
224 #define DEF_CASE(NAME) \
226 NAME##Stub stub(key, isolate); \
227 CodeStub* pstub = &stub; \
228 call(pstub, value_out); \
231 CODE_STUB_LIST(DEF_CASE)
241 static void InitializeDescriptorDispatchedCall(CodeStub* stub,
243 CodeStubDescriptor* descriptor_out =
244 reinterpret_cast<CodeStubDescriptor*>(value_out);
245 stub->InitializeDescriptor(descriptor_out);
246 descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
250 void CodeStub::InitializeDescriptor(Isolate* isolate, uint32_t key,
251 CodeStubDescriptor* desc) {
252 void** value_out = reinterpret_cast<void**>(desc);
253 Dispatch(isolate, key, value_out, &InitializeDescriptorDispatchedCall);
257 void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
258 Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
259 // Code stubs with special cache cannot be recreated from stub key.
260 *code_out = stub->UseSpecialCache() ? Handle<Code>() : stub->GetCode();
264 MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
265 HandleScope scope(isolate);
267 void** value_out = reinterpret_cast<void**>(&code);
268 Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
269 return scope.CloseAndEscape(code);
274 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
275 // Generate the uninitialized versions of the stub.
276 for (int op = Token::BIT_OR; op <= Token::MOD; ++op) {
277 BinaryOpICStub stub(isolate, static_cast<Token::Value>(op), Strength::WEAK);
281 // Generate special versions of the stub.
282 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
286 void BinaryOpICStub::PrintState(std::ostream& os) const { // NOLINT
292 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
293 const BinaryOpICState& state) {
294 BinaryOpICStub stub(isolate, state);
300 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
301 // Generate special versions of the stub.
302 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
306 void BinaryOpICWithAllocationSiteStub::PrintState(
307 std::ostream& os) const { // NOLINT
313 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
314 Isolate* isolate, const BinaryOpICState& state) {
315 if (state.CouldCreateAllocationMementos()) {
316 BinaryOpICWithAllocationSiteStub stub(isolate, state);
322 std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags) {
324 case STRING_ADD_CHECK_NONE:
325 return os << "CheckNone";
326 case STRING_ADD_CHECK_LEFT:
327 return os << "CheckLeft";
328 case STRING_ADD_CHECK_RIGHT:
329 return os << "CheckRight";
330 case STRING_ADD_CHECK_BOTH:
331 return os << "CheckBoth";
338 void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT
339 os << "StringAddStub_" << flags() << "_" << pretenure_flag();
343 void StringAddTFStub::PrintBaseName(std::ostream& os) const { // NOLINT
344 os << "StringAddTFStub_" << flags() << "_" << pretenure_flag();
348 InlineCacheState CompareICStub::GetICState() const {
349 CompareICState::State state = Max(left(), right());
351 case CompareICState::UNINITIALIZED:
352 return ::v8::internal::UNINITIALIZED;
353 case CompareICState::SMI:
354 case CompareICState::NUMBER:
355 case CompareICState::INTERNALIZED_STRING:
356 case CompareICState::STRING:
357 case CompareICState::UNIQUE_NAME:
358 case CompareICState::OBJECT:
359 case CompareICState::KNOWN_OBJECT:
361 case CompareICState::GENERIC:
362 return ::v8::internal::GENERIC;
365 return ::v8::internal::UNINITIALIZED;
369 Condition CompareICStub::GetCondition() const {
370 return CompareIC::ComputeCondition(op());
374 void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
375 DCHECK(*known_map_ != NULL);
376 Isolate* isolate = new_object->GetIsolate();
377 Factory* factory = isolate->factory();
378 return Map::UpdateCodeCache(known_map_,
380 factory->strict_compare_ic_string() :
381 factory->compare_ic_string(),
386 bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
387 Factory* factory = isolate()->factory();
388 Code::Flags flags = Code::ComputeFlags(
391 DCHECK(op() == Token::EQ || op() == Token::EQ_STRICT);
392 Handle<Object> probe(
393 known_map_->FindInCodeCache(
395 *factory->strict_compare_ic_string() :
396 *factory->compare_ic_string(),
399 if (probe->IsCode()) {
400 *code_out = Code::cast(*probe);
402 CompareICStub decode((*code_out)->stub_key(), isolate());
403 DCHECK(op() == decode.op());
404 DCHECK(left() == decode.left());
405 DCHECK(right() == decode.right());
406 DCHECK(state() == decode.state());
414 void CompareICStub::Generate(MacroAssembler* masm) {
416 case CompareICState::UNINITIALIZED:
419 case CompareICState::SMI:
422 case CompareICState::NUMBER:
423 GenerateNumbers(masm);
425 case CompareICState::STRING:
426 GenerateStrings(masm);
428 case CompareICState::INTERNALIZED_STRING:
429 GenerateInternalizedStrings(masm);
431 case CompareICState::UNIQUE_NAME:
432 GenerateUniqueNames(masm);
434 case CompareICState::OBJECT:
435 GenerateObjects(masm);
437 case CompareICState::KNOWN_OBJECT:
438 DCHECK(*known_map_ != NULL);
439 GenerateKnownObjects(masm);
441 case CompareICState::GENERIC:
442 GenerateGeneric(masm);
448 void CompareNilICStub::UpdateStatus(Handle<Object> object) {
449 State state = this->state();
450 DCHECK(!state.Contains(GENERIC));
451 State old_state = state;
452 if (object->IsNull()) {
453 state.Add(NULL_TYPE);
454 } else if (object->IsUndefined()) {
455 state.Add(UNDEFINED);
456 } else if (object->IsUndetectableObject() ||
457 object->IsOddball() ||
458 !object->IsHeapObject()) {
461 } else if (IsMonomorphic()) {
465 state.Add(MONOMORPHIC_MAP);
467 TraceTransition(old_state, state);
468 set_sub_minor_key(TypesBits::update(sub_minor_key(), state.ToIntegral()));
474 Handle<JSFunction> GetFunction(Isolate* isolate, const char* name) {
475 v8::ExtensionConfiguration no_extensions;
476 MaybeHandle<Object> fun = Object::GetProperty(
477 isolate, isolate->factory()->code_stub_exports_object(), name);
478 Handle<JSFunction> function = Handle<JSFunction>::cast(fun.ToHandleChecked());
479 DCHECK(!function->IsUndefined() &&
480 "JavaScript implementation of stub not found");
486 Handle<Code> TurboFanCodeStub::GenerateCode() {
487 // Get the outer ("stub generator") function.
488 const char* name = CodeStub::MajorName(MajorKey(), false);
489 Handle<JSFunction> outer = GetFunction(isolate(), name);
490 DCHECK_EQ(2, outer->shared()->length());
492 // Invoke the outer function to get the stub itself.
493 Factory* factory = isolate()->factory();
494 Handle<Object> call_conv = factory->InternalizeUtf8String(name);
495 Handle<Object> minor_key = factory->NewNumber(MinorKey());
496 Handle<Object> args[] = {call_conv, minor_key};
497 MaybeHandle<Object> result = Execution::Call(
498 isolate(), outer, factory->undefined_value(), 2, args, false);
499 Handle<JSFunction> inner = Handle<JSFunction>::cast(result.ToHandleChecked());
500 // Just to make sure nobody calls this...
501 inner->set_code(isolate()->builtins()->builtin(Builtins::kIllegal));
504 // Build a "hybrid" CompilationInfo for a JSFunction/CodeStub pair.
505 ParseInfo parse_info(&zone, inner);
506 CompilationInfo info(&parse_info);
507 info.SetFunctionType(GetCallInterfaceDescriptor().GetFunctionType());
508 info.MarkAsContextSpecializing();
510 return info.GenerateCodeStub();
514 template<class StateType>
515 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
516 // Note: Although a no-op transition is semantically OK, it is hinting at a
517 // bug somewhere in our state transition machinery.
519 if (!FLAG_trace_ic) return;
523 os << ": " << from << "=>" << to << "]" << std::endl;
527 void CompareNilICStub::PrintBaseName(std::ostream& os) const { // NOLINT
528 CodeStub::PrintBaseName(os);
529 os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
533 void CompareNilICStub::PrintState(std::ostream& os) const { // NOLINT
538 // TODO(svenpanne) Make this a real infix_ostream_iterator.
539 class SimpleListPrinter {
541 explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {}
543 void Add(const char* s) {
558 std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s) {
560 SimpleListPrinter p(os);
561 if (s.IsEmpty()) p.Add("None");
562 if (s.Contains(CompareNilICStub::UNDEFINED)) p.Add("Undefined");
563 if (s.Contains(CompareNilICStub::NULL_TYPE)) p.Add("Null");
564 if (s.Contains(CompareNilICStub::MONOMORPHIC_MAP)) p.Add("MonomorphicMap");
565 if (s.Contains(CompareNilICStub::GENERIC)) p.Add("Generic");
570 Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
571 State state = this->state();
572 if (state.Contains(CompareNilICStub::GENERIC)) return Type::Any(zone);
574 Type* result = Type::None(zone);
575 if (state.Contains(CompareNilICStub::UNDEFINED)) {
576 result = Type::Union(result, Type::Undefined(zone), zone);
578 if (state.Contains(CompareNilICStub::NULL_TYPE)) {
579 result = Type::Union(result, Type::Null(zone), zone);
581 if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
583 map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
584 result = Type::Union(result, type, zone);
591 Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
592 Type* output_type = GetType(zone, map);
594 nil_value() == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
595 return Type::Union(output_type, nil_type, zone);
599 void CallIC_ArrayStub::PrintState(std::ostream& os) const { // NOLINT
600 os << state() << " (Array)";
604 void CallICStub::PrintState(std::ostream& os) const { // NOLINT
609 void InstanceofStub::PrintName(std::ostream& os) const { // NOLINT
610 os << "InstanceofStub";
611 if (HasArgsInRegisters()) os << "_REGS";
612 if (HasCallSiteInlineCheck()) os << "_INLINE";
613 if (ReturnTrueFalseObject()) os << "_TRUEFALSE";
617 void JSEntryStub::FinishCode(Handle<Code> code) {
618 Handle<FixedArray> handler_table =
619 code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
620 handler_table->set(0, Smi::FromInt(handler_offset_));
621 code->set_handler_table(*handler_table);
625 void LoadDictionaryElementStub::InitializeDescriptor(
626 CodeStubDescriptor* descriptor) {
627 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
631 void KeyedLoadGenericStub::InitializeDescriptor(
632 CodeStubDescriptor* descriptor) {
633 descriptor->Initialize(
634 Runtime::FunctionForId(is_strong(language_mode())
635 ? Runtime::kKeyedGetPropertyStrong
636 : Runtime::kKeyedGetProperty)->entry);
640 void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
641 if (kind() == Code::STORE_IC) {
642 descriptor->Initialize(FUNCTION_ADDR(StoreIC_MissFromStubFailure));
643 } else if (kind() == Code::KEYED_LOAD_IC) {
644 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
645 } else if (kind() == Code::KEYED_STORE_IC) {
646 descriptor->Initialize(FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
651 CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() const {
652 if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
653 return LoadWithVectorDescriptor(isolate());
655 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC);
656 return StoreDescriptor(isolate());
661 void StoreFastElementStub::InitializeDescriptor(
662 CodeStubDescriptor* descriptor) {
663 descriptor->Initialize(FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
667 void ElementsTransitionAndStoreStub::InitializeDescriptor(
668 CodeStubDescriptor* descriptor) {
669 descriptor->Initialize(FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss));
673 CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor()
675 return StoreTransitionDescriptor(isolate());
679 void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
680 descriptor->Initialize(
681 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry);
685 void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
688 void TypeofStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {}
691 void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
692 NumberToStringDescriptor call_descriptor(isolate());
693 descriptor->Initialize(
694 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry);
698 void FastCloneShallowArrayStub::InitializeDescriptor(
699 CodeStubDescriptor* descriptor) {
700 FastCloneShallowArrayDescriptor call_descriptor(isolate());
701 descriptor->Initialize(
702 Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
706 void FastCloneShallowObjectStub::InitializeDescriptor(
707 CodeStubDescriptor* descriptor) {
708 FastCloneShallowObjectDescriptor call_descriptor(isolate());
709 descriptor->Initialize(
710 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
714 void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
717 void CreateWeakCellStub::InitializeDescriptor(CodeStubDescriptor* d) {}
720 void RegExpConstructResultStub::InitializeDescriptor(
721 CodeStubDescriptor* descriptor) {
722 descriptor->Initialize(
723 Runtime::FunctionForId(Runtime::kRegExpConstructResultRT)->entry);
727 void LoadGlobalViaContextStub::InitializeDescriptor(
728 CodeStubDescriptor* descriptor) {
729 // Must never deoptimize.
730 descriptor->Initialize(FUNCTION_ADDR(UnexpectedStubMiss));
734 void StoreGlobalViaContextStub::InitializeDescriptor(
735 CodeStubDescriptor* descriptor) {
736 // Must never deoptimize.
737 descriptor->Initialize(FUNCTION_ADDR(UnexpectedStubMiss));
741 void TransitionElementsKindStub::InitializeDescriptor(
742 CodeStubDescriptor* descriptor) {
743 descriptor->Initialize(
744 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
748 void AllocateHeapNumberStub::InitializeDescriptor(
749 CodeStubDescriptor* descriptor) {
750 descriptor->Initialize(
751 Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry);
755 void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
756 descriptor->Initialize(FUNCTION_ADDR(CompareNilIC_Miss));
757 descriptor->SetMissHandler(
758 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate()));
762 void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
763 descriptor->Initialize(FUNCTION_ADDR(ToBooleanIC_Miss));
764 descriptor->SetMissHandler(
765 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate()));
769 void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
770 descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_Miss));
771 descriptor->SetMissHandler(
772 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate()));
776 void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
777 CodeStubDescriptor* descriptor) {
778 descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite));
782 void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
783 descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAddRT)->entry);
787 void GrowArrayElementsStub::InitializeDescriptor(
788 CodeStubDescriptor* descriptor) {
789 descriptor->Initialize(
790 Runtime::FunctionForId(Runtime::kGrowArrayElements)->entry);
794 void TypeofStub::GenerateAheadOfTime(Isolate* isolate) {
795 TypeofStub stub(isolate);
800 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
801 CreateAllocationSiteStub stub(isolate);
806 void CreateWeakCellStub::GenerateAheadOfTime(Isolate* isolate) {
807 CreateWeakCellStub stub(isolate);
812 void StoreElementStub::Generate(MacroAssembler* masm) {
813 switch (elements_kind()) {
815 case FAST_HOLEY_ELEMENTS:
816 case FAST_SMI_ELEMENTS:
817 case FAST_HOLEY_SMI_ELEMENTS:
818 case FAST_DOUBLE_ELEMENTS:
819 case FAST_HOLEY_DOUBLE_ELEMENTS:
820 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
821 case EXTERNAL_##TYPE##_ELEMENTS: \
822 case TYPE##_ELEMENTS:
824 TYPED_ARRAYS(TYPED_ARRAY_CASE)
825 #undef TYPED_ARRAY_CASE
828 case DICTIONARY_ELEMENTS:
829 ElementHandlerCompiler::GenerateStoreSlow(masm);
831 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
832 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
840 void StoreFastElementStub::GenerateAheadOfTime(Isolate* isolate) {
841 StoreFastElementStub(isolate, false, FAST_HOLEY_ELEMENTS, STANDARD_STORE)
843 StoreFastElementStub(isolate, false, FAST_HOLEY_ELEMENTS,
844 STORE_AND_GROW_NO_TRANSITION).GetCode();
845 for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
846 ElementsKind kind = static_cast<ElementsKind>(i);
847 StoreFastElementStub(isolate, true, kind, STANDARD_STORE).GetCode();
848 StoreFastElementStub(isolate, true, kind, STORE_AND_GROW_NO_TRANSITION)
854 void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
857 GenerateReadElement(masm);
859 case NEW_SLOPPY_FAST:
860 GenerateNewSloppyFast(masm);
862 case NEW_SLOPPY_SLOW:
863 GenerateNewSloppySlow(masm);
866 GenerateNewStrict(masm);
872 void RestParamAccessStub::Generate(MacroAssembler* masm) {
877 void ArgumentsAccessStub::PrintName(std::ostream& os) const { // NOLINT
878 os << "ArgumentsAccessStub_";
883 case NEW_SLOPPY_FAST:
884 os << "NewSloppyFast";
886 case NEW_SLOPPY_SLOW:
887 os << "NewSloppySlow";
897 void RestParamAccessStub::PrintName(std::ostream& os) const { // NOLINT
898 os << "RestParamAccessStub_";
902 void CallFunctionStub::PrintName(std::ostream& os) const { // NOLINT
903 os << "CallFunctionStub_Args" << argc();
907 void CallConstructStub::PrintName(std::ostream& os) const { // NOLINT
908 os << "CallConstructStub";
909 if (RecordCallTarget()) os << "_Recording";
913 void ArrayConstructorStub::PrintName(std::ostream& os) const { // NOLINT
914 os << "ArrayConstructorStub";
915 switch (argument_count()) {
926 os << "_More_Than_One";
933 std::ostream& ArrayConstructorStubBase::BasePrintName(
934 std::ostream& os, // NOLINT
935 const char* name) const {
936 os << name << "_" << ElementsKindToString(elements_kind());
937 if (override_mode() == DISABLE_ALLOCATION_SITES) {
938 os << "_DISABLE_ALLOCATION_SITES";
944 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
945 Types new_types = types();
946 Types old_types = new_types;
947 bool to_boolean_value = new_types.UpdateStatus(object);
948 TraceTransition(old_types, new_types);
949 set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToIntegral()));
950 return to_boolean_value;
954 void ToBooleanStub::PrintState(std::ostream& os) const { // NOLINT
959 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) {
961 SimpleListPrinter p(os);
962 if (s.IsEmpty()) p.Add("None");
963 if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined");
964 if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool");
965 if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null");
966 if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi");
967 if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject");
968 if (s.Contains(ToBooleanStub::STRING)) p.Add("String");
969 if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol");
970 if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber");
971 if (s.Contains(ToBooleanStub::SIMD_VALUE)) p.Add("SimdValue");
976 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
977 if (object->IsUndefined()) {
980 } else if (object->IsBoolean()) {
982 return object->IsTrue();
983 } else if (object->IsNull()) {
986 } else if (object->IsSmi()) {
988 return Smi::cast(*object)->value() != 0;
989 } else if (object->IsSpecObject()) {
991 return !object->IsUndetectableObject();
992 } else if (object->IsString()) {
994 return !object->IsUndetectableObject() &&
995 String::cast(*object)->length() != 0;
996 } else if (object->IsSymbol()) {
999 } else if (object->IsHeapNumber()) {
1000 DCHECK(!object->IsUndetectableObject());
1002 double value = HeapNumber::cast(*object)->value();
1003 return value != 0 && !std::isnan(value);
1004 } else if (object->IsFloat32x4()) {
1008 // We should never see an internal object at runtime here!
1015 bool ToBooleanStub::Types::NeedsMap() const {
1016 return Contains(ToBooleanStub::SPEC_OBJECT) ||
1017 Contains(ToBooleanStub::STRING) || Contains(ToBooleanStub::SYMBOL) ||
1018 Contains(ToBooleanStub::HEAP_NUMBER) ||
1019 Contains(ToBooleanStub::SIMD_VALUE);
1023 bool ToBooleanStub::Types::CanBeUndetectable() const {
1024 return Contains(ToBooleanStub::SPEC_OBJECT)
1025 || Contains(ToBooleanStub::STRING);
1029 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
1030 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
1031 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
1037 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
1038 intptr_t stack_pointer,
1040 FunctionEntryHook entry_hook = isolate->function_entry_hook();
1041 DCHECK(entry_hook != NULL);
1042 entry_hook(function, stack_pointer);
1046 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
1047 : PlatformCodeStub(isolate) {
1048 minor_key_ = ArgumentCountBits::encode(ANY);
1049 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1053 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
1055 : PlatformCodeStub(isolate) {
1056 if (argument_count == 0) {
1057 minor_key_ = ArgumentCountBits::encode(NONE);
1058 } else if (argument_count == 1) {
1059 minor_key_ = ArgumentCountBits::encode(ONE);
1060 } else if (argument_count >= 2) {
1061 minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
1065 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1069 InternalArrayConstructorStub::InternalArrayConstructorStub(
1070 Isolate* isolate) : PlatformCodeStub(isolate) {
1071 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1075 Representation RepresentationFromType(Type* type) {
1076 if (type->Is(Type::UntaggedSigned()) || type->Is(Type::UntaggedUnsigned())) {
1077 return Representation::Integer32();
1080 if (type->Is(Type::TaggedSigned())) {
1081 return Representation::Smi();
1084 if (type->Is(Type::UntaggedPointer())) {
1085 return Representation::External();
1088 DCHECK(!type->Is(Type::Untagged()));
1089 return Representation::Tagged();
1091 } // namespace internal