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 CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
23 : call_descriptor_(stub->GetCallInterfaceDescriptor()),
24 stack_parameter_count_(no_reg),
25 hint_stack_parameter_count_(-1),
26 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
27 deoptimization_handler_(NULL),
28 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
30 has_miss_handler_(false) {
31 stub->InitializeDescriptor(this);
35 CodeStubDescriptor::CodeStubDescriptor(Isolate* isolate, uint32_t stub_key)
36 : stack_parameter_count_(no_reg),
37 hint_stack_parameter_count_(-1),
38 function_mode_(NOT_JS_FUNCTION_STUB_MODE),
39 deoptimization_handler_(NULL),
40 handler_arguments_mode_(DONT_PASS_ARGUMENTS),
42 has_miss_handler_(false) {
43 CodeStub::InitializeDescriptor(isolate, stub_key, this);
47 void CodeStubDescriptor::Initialize(Address deoptimization_handler,
48 int hint_stack_parameter_count,
49 StubFunctionMode function_mode) {
50 deoptimization_handler_ = deoptimization_handler;
51 hint_stack_parameter_count_ = hint_stack_parameter_count;
52 function_mode_ = function_mode;
56 void CodeStubDescriptor::Initialize(Register stack_parameter_count,
57 Address deoptimization_handler,
58 int hint_stack_parameter_count,
59 StubFunctionMode function_mode,
60 HandlerArgumentsMode handler_mode) {
61 Initialize(deoptimization_handler, hint_stack_parameter_count, function_mode);
62 stack_parameter_count_ = stack_parameter_count;
63 handler_arguments_mode_ = handler_mode;
67 bool CodeStub::FindCodeInCache(Code** code_out) {
68 UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
69 int index = stubs->FindEntry(GetKey());
70 if (index != UnseededNumberDictionary::kNotFound) {
71 *code_out = Code::cast(stubs->ValueAt(index));
78 void CodeStub::RecordCodeGeneration(Handle<Code> code) {
79 std::ostringstream os;
82 CodeCreateEvent(Logger::STUB_TAG, *code, os.str().c_str()));
83 Counters* counters = isolate()->counters();
84 counters->total_stubs_code_size()->Increment(code->instruction_size());
86 code->VerifyEmbeddedObjects();
91 Code::Kind CodeStub::GetCodeKind() const {
96 Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) {
97 Handle<Code> ic = GetCode();
98 ic = isolate()->factory()->CopyCode(ic);
99 ic->FindAndReplace(pattern);
100 RecordCodeGeneration(ic);
105 Handle<Code> PlatformCodeStub::GenerateCode() {
106 Factory* factory = isolate()->factory();
108 // Generate the new code.
109 MacroAssembler masm(isolate(), NULL, 256);
112 // Update the static counter each time a new code stub is generated.
113 isolate()->counters()->code_stubs()->Increment();
115 // Generate the code for the stub.
116 masm.set_generating_stub(true);
117 // TODO(yangguo): remove this once we can serialize IC stubs.
118 masm.enable_serializer();
119 NoCurrentFrameScope scope(&masm);
123 // Create the code object.
127 // Copy the generated code into a heap object.
128 Code::Flags flags = Code::ComputeFlags(
133 Handle<Code> new_object = factory->NewCode(
134 desc, flags, masm.CodeObject(), NeedsImmovableCode());
139 Handle<Code> CodeStub::GetCode() {
140 Heap* heap = isolate()->heap();
142 if (UseSpecialCache() ? FindCodeInSpecialCache(&code)
143 : FindCodeInCache(&code)) {
144 DCHECK(GetCodeKind() == code->kind());
145 return Handle<Code>(code);
149 HandleScope scope(isolate());
151 Handle<Code> new_object = GenerateCode();
152 new_object->set_stub_key(GetKey());
153 FinishCode(new_object);
154 RecordCodeGeneration(new_object);
156 #ifdef ENABLE_DISASSEMBLER
157 if (FLAG_print_code_stubs) {
158 CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
159 OFStream os(trace_scope.file());
160 std::ostringstream name;
162 new_object->Disassemble(name.str().c_str(), os);
167 if (UseSpecialCache()) {
168 AddToSpecialCache(new_object);
170 // Update the dictionary and the root in Heap.
171 Handle<UnseededNumberDictionary> dict =
172 UnseededNumberDictionary::AtNumberPut(
173 Handle<UnseededNumberDictionary>(heap->code_stubs()),
176 heap->public_set_code_stubs(*dict);
182 DCHECK(!NeedsImmovableCode() ||
183 heap->lo_space()->Contains(code) ||
184 heap->code_space()->FirstPage()->Contains(code->address()));
185 return Handle<Code>(code, isolate());
189 const char* CodeStub::MajorName(CodeStub::Major major_key,
190 bool allow_unknown_keys) {
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(), false);
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),
273 LanguageMode::SLOPPY);
277 // Generate special versions of the stub.
278 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
282 void BinaryOpICStub::PrintState(std::ostream& os) const { // NOLINT
288 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
289 const BinaryOpICState& state) {
290 BinaryOpICStub stub(isolate, state);
296 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
297 // Generate special versions of the stub.
298 BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
302 void BinaryOpICWithAllocationSiteStub::PrintState(
303 std::ostream& os) const { // NOLINT
309 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
310 Isolate* isolate, const BinaryOpICState& state) {
311 if (state.CouldCreateAllocationMementos()) {
312 BinaryOpICWithAllocationSiteStub stub(isolate, state);
318 std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags) {
320 case STRING_ADD_CHECK_NONE:
321 return os << "CheckNone";
322 case STRING_ADD_CHECK_LEFT:
323 return os << "CheckLeft";
324 case STRING_ADD_CHECK_RIGHT:
325 return os << "CheckRight";
326 case STRING_ADD_CHECK_BOTH:
327 return os << "CheckBoth";
334 void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT
335 os << "StringAddStub_" << flags() << "_" << pretenure_flag();
339 void StringAddTFStub::PrintBaseName(std::ostream& os) const { // NOLINT
340 os << "StringAddTFStub_" << flags() << "_" << pretenure_flag();
344 InlineCacheState CompareICStub::GetICState() const {
345 CompareICState::State state = Max(left(), right());
347 case CompareICState::UNINITIALIZED:
348 return ::v8::internal::UNINITIALIZED;
349 case CompareICState::SMI:
350 case CompareICState::NUMBER:
351 case CompareICState::INTERNALIZED_STRING:
352 case CompareICState::STRING:
353 case CompareICState::UNIQUE_NAME:
354 case CompareICState::OBJECT:
355 case CompareICState::KNOWN_OBJECT:
357 case CompareICState::GENERIC:
358 return ::v8::internal::GENERIC;
361 return ::v8::internal::UNINITIALIZED;
365 Condition CompareICStub::GetCondition() const {
366 return CompareIC::ComputeCondition(op());
370 void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
371 DCHECK(*known_map_ != NULL);
372 Isolate* isolate = new_object->GetIsolate();
373 Factory* factory = isolate->factory();
374 return Map::UpdateCodeCache(known_map_,
376 factory->strict_compare_ic_string() :
377 factory->compare_ic_string(),
382 bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
383 Factory* factory = isolate()->factory();
384 Code::Flags flags = Code::ComputeFlags(
387 DCHECK(op() == Token::EQ || op() == Token::EQ_STRICT);
388 Handle<Object> probe(
389 known_map_->FindInCodeCache(
391 *factory->strict_compare_ic_string() :
392 *factory->compare_ic_string(),
395 if (probe->IsCode()) {
396 *code_out = Code::cast(*probe);
398 CompareICStub decode((*code_out)->stub_key(), isolate());
399 DCHECK(op() == decode.op());
400 DCHECK(left() == decode.left());
401 DCHECK(right() == decode.right());
402 DCHECK(state() == decode.state());
410 void CompareICStub::Generate(MacroAssembler* masm) {
412 case CompareICState::UNINITIALIZED:
415 case CompareICState::SMI:
418 case CompareICState::NUMBER:
419 GenerateNumbers(masm);
421 case CompareICState::STRING:
422 GenerateStrings(masm);
424 case CompareICState::INTERNALIZED_STRING:
425 GenerateInternalizedStrings(masm);
427 case CompareICState::UNIQUE_NAME:
428 GenerateUniqueNames(masm);
430 case CompareICState::OBJECT:
431 GenerateObjects(masm);
433 case CompareICState::KNOWN_OBJECT:
434 DCHECK(*known_map_ != NULL);
435 GenerateKnownObjects(masm);
437 case CompareICState::GENERIC:
438 GenerateGeneric(masm);
444 void CompareNilICStub::UpdateStatus(Handle<Object> object) {
445 State state = this->state();
446 DCHECK(!state.Contains(GENERIC));
447 State old_state = state;
448 if (object->IsNull()) {
449 state.Add(NULL_TYPE);
450 } else if (object->IsUndefined()) {
451 state.Add(UNDEFINED);
452 } else if (object->IsUndetectableObject() ||
453 object->IsOddball() ||
454 !object->IsHeapObject()) {
457 } else if (IsMonomorphic()) {
461 state.Add(MONOMORPHIC_MAP);
463 TraceTransition(old_state, state);
464 set_sub_minor_key(TypesBits::update(sub_minor_key(), state.ToIntegral()));
470 Handle<JSFunction> GetFunction(Isolate* isolate, const char* name) {
471 v8::ExtensionConfiguration no_extensions;
472 Handle<Context> ctx = isolate->bootstrapper()->CreateEnvironment(
473 MaybeHandle<JSGlobalProxy>(), v8::Handle<v8::ObjectTemplate>(),
475 Handle<JSBuiltinsObject> builtins = handle(ctx->builtins());
476 MaybeHandle<Object> fun = Object::GetProperty(isolate, builtins, name);
477 Handle<JSFunction> function = Handle<JSFunction>::cast(fun.ToHandleChecked());
478 DCHECK(!function->IsUndefined() &&
479 "JavaScript implementation of stub not found");
485 Handle<Code> TurboFanCodeStub::GenerateCode() {
486 // Get the outer ("stub generator") function.
487 const char* name = CodeStub::MajorName(MajorKey(), false);
488 Handle<JSFunction> outer = GetFunction(isolate(), name);
489 DCHECK_EQ(2, outer->shared()->length());
491 // Invoke the outer function to get the stub itself.
492 Factory* factory = isolate()->factory();
493 Handle<Object> call_conv = factory->InternalizeUtf8String(name);
494 Handle<Object> minor_key = factory->NewNumber(MinorKey());
495 Handle<Object> args[] = {call_conv, minor_key};
496 MaybeHandle<Object> result = Execution::Call(
497 isolate(), outer, factory->undefined_value(), 2, args, false);
498 Handle<JSFunction> inner = Handle<JSFunction>::cast(result.ToHandleChecked());
499 // Just to make sure nobody calls this...
500 inner->set_code(isolate()->builtins()->builtin(Builtins::kIllegal));
503 // Build a "hybrid" CompilationInfo for a JSFunction/CodeStub pair.
504 ParseInfo parse_info(&zone, inner);
505 CompilationInfo info(&parse_info);
507 return info.GenerateCodeStub();
511 template<class StateType>
512 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
513 // Note: Although a no-op transition is semantically OK, it is hinting at a
514 // bug somewhere in our state transition machinery.
516 if (!FLAG_trace_ic) return;
520 os << ": " << from << "=>" << to << "]" << std::endl;
524 void CompareNilICStub::PrintBaseName(std::ostream& os) const { // NOLINT
525 CodeStub::PrintBaseName(os);
526 os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
530 void CompareNilICStub::PrintState(std::ostream& os) const { // NOLINT
535 // TODO(svenpanne) Make this a real infix_ostream_iterator.
536 class SimpleListPrinter {
538 explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {}
540 void Add(const char* s) {
555 std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s) {
557 SimpleListPrinter p(os);
558 if (s.IsEmpty()) p.Add("None");
559 if (s.Contains(CompareNilICStub::UNDEFINED)) p.Add("Undefined");
560 if (s.Contains(CompareNilICStub::NULL_TYPE)) p.Add("Null");
561 if (s.Contains(CompareNilICStub::MONOMORPHIC_MAP)) p.Add("MonomorphicMap");
562 if (s.Contains(CompareNilICStub::GENERIC)) p.Add("Generic");
567 Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
568 State state = this->state();
569 if (state.Contains(CompareNilICStub::GENERIC)) return Type::Any(zone);
571 Type* result = Type::None(zone);
572 if (state.Contains(CompareNilICStub::UNDEFINED)) {
573 result = Type::Union(result, Type::Undefined(zone), zone);
575 if (state.Contains(CompareNilICStub::NULL_TYPE)) {
576 result = Type::Union(result, Type::Null(zone), zone);
578 if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
580 map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
581 result = Type::Union(result, type, zone);
588 Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
589 Type* output_type = GetType(zone, map);
591 nil_value() == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
592 return Type::Union(output_type, nil_type, zone);
596 void CallIC_ArrayStub::PrintState(std::ostream& os) const { // NOLINT
597 os << state() << " (Array)";
601 void CallICStub::PrintState(std::ostream& os) const { // NOLINT
606 void InstanceofStub::PrintName(std::ostream& os) const { // NOLINT
607 os << "InstanceofStub";
608 if (HasArgsInRegisters()) os << "_REGS";
609 if (HasCallSiteInlineCheck()) os << "_INLINE";
610 if (ReturnTrueFalseObject()) os << "_TRUEFALSE";
614 void JSEntryStub::FinishCode(Handle<Code> code) {
615 Handle<FixedArray> handler_table =
616 code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
617 handler_table->set(0, Smi::FromInt(handler_offset_));
618 code->set_handler_table(*handler_table);
622 void LoadDictionaryElementStub::InitializeDescriptor(
623 CodeStubDescriptor* descriptor) {
624 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
628 void KeyedLoadGenericStub::InitializeDescriptor(
629 CodeStubDescriptor* descriptor) {
630 descriptor->Initialize(
631 Runtime::FunctionForId(Runtime::kKeyedGetProperty)->entry);
635 void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
636 if (kind() == Code::STORE_IC) {
637 descriptor->Initialize(FUNCTION_ADDR(StoreIC_MissFromStubFailure));
638 } else if (kind() == Code::KEYED_LOAD_IC) {
639 descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
640 } else if (kind() == Code::KEYED_STORE_IC) {
641 descriptor->Initialize(FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
646 CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() {
647 if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
648 return LoadWithVectorDescriptor(isolate());
650 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC);
651 return StoreDescriptor(isolate());
656 void StoreFastElementStub::InitializeDescriptor(
657 CodeStubDescriptor* descriptor) {
658 descriptor->Initialize(FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
662 void ElementsTransitionAndStoreStub::InitializeDescriptor(
663 CodeStubDescriptor* descriptor) {
664 descriptor->Initialize(FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss));
668 CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor() {
669 return StoreTransitionDescriptor(isolate());
673 void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
674 descriptor->Initialize(
675 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry);
679 void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
682 void TypeofStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {}
685 void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
686 NumberToStringDescriptor call_descriptor(isolate());
687 descriptor->Initialize(
688 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry);
692 void FastCloneShallowArrayStub::InitializeDescriptor(
693 CodeStubDescriptor* descriptor) {
694 FastCloneShallowArrayDescriptor call_descriptor(isolate());
695 descriptor->Initialize(
696 Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
700 void FastCloneShallowObjectStub::InitializeDescriptor(
701 CodeStubDescriptor* descriptor) {
702 FastCloneShallowObjectDescriptor call_descriptor(isolate());
703 descriptor->Initialize(
704 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
708 void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
711 void CreateWeakCellStub::InitializeDescriptor(CodeStubDescriptor* d) {}
714 void RegExpConstructResultStub::InitializeDescriptor(
715 CodeStubDescriptor* descriptor) {
716 descriptor->Initialize(
717 Runtime::FunctionForId(Runtime::kRegExpConstructResultRT)->entry);
721 void TransitionElementsKindStub::InitializeDescriptor(
722 CodeStubDescriptor* descriptor) {
723 descriptor->Initialize(
724 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
728 void AllocateHeapNumberStub::InitializeDescriptor(
729 CodeStubDescriptor* descriptor) {
730 descriptor->Initialize(
731 Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry);
735 void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
736 descriptor->Initialize(FUNCTION_ADDR(CompareNilIC_Miss));
737 descriptor->SetMissHandler(
738 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate()));
742 void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
743 descriptor->Initialize(FUNCTION_ADDR(ToBooleanIC_Miss));
744 descriptor->SetMissHandler(
745 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate()));
749 void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
750 descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_Miss));
751 descriptor->SetMissHandler(
752 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate()));
756 void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
757 CodeStubDescriptor* descriptor) {
758 descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite));
762 void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
763 descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAddRT)->entry);
767 void GrowArrayElementsStub::InitializeDescriptor(
768 CodeStubDescriptor* descriptor) {
769 descriptor->Initialize(
770 Runtime::FunctionForId(Runtime::kGrowArrayElements)->entry);
774 void TypeofStub::GenerateAheadOfTime(Isolate* isolate) {
775 TypeofStub stub(isolate);
780 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
781 CreateAllocationSiteStub stub(isolate);
786 void CreateWeakCellStub::GenerateAheadOfTime(Isolate* isolate) {
787 CreateWeakCellStub stub(isolate);
792 void StoreElementStub::Generate(MacroAssembler* masm) {
793 switch (elements_kind()) {
795 case FAST_HOLEY_ELEMENTS:
796 case FAST_SMI_ELEMENTS:
797 case FAST_HOLEY_SMI_ELEMENTS:
798 case FAST_DOUBLE_ELEMENTS:
799 case FAST_HOLEY_DOUBLE_ELEMENTS:
800 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
801 case EXTERNAL_##TYPE##_ELEMENTS: \
802 case TYPE##_ELEMENTS:
804 TYPED_ARRAYS(TYPED_ARRAY_CASE)
805 #undef TYPED_ARRAY_CASE
808 case DICTIONARY_ELEMENTS:
809 ElementHandlerCompiler::GenerateStoreSlow(masm);
811 case SLOPPY_ARGUMENTS_ELEMENTS:
819 void StoreFastElementStub::GenerateAheadOfTime(Isolate* isolate) {
820 StoreFastElementStub(isolate, false, FAST_HOLEY_ELEMENTS, STANDARD_STORE)
822 StoreFastElementStub(isolate, false, FAST_HOLEY_ELEMENTS,
823 STORE_AND_GROW_NO_TRANSITION).GetCode();
824 for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
825 ElementsKind kind = static_cast<ElementsKind>(i);
826 StoreFastElementStub(isolate, true, kind, STANDARD_STORE).GetCode();
827 StoreFastElementStub(isolate, true, kind, STORE_AND_GROW_NO_TRANSITION)
833 void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
836 GenerateReadElement(masm);
838 case NEW_SLOPPY_FAST:
839 GenerateNewSloppyFast(masm);
841 case NEW_SLOPPY_SLOW:
842 GenerateNewSloppySlow(masm);
845 GenerateNewStrict(masm);
851 void RestParamAccessStub::Generate(MacroAssembler* masm) {
856 void ArgumentsAccessStub::PrintName(std::ostream& os) const { // NOLINT
857 os << "ArgumentsAccessStub_";
862 case NEW_SLOPPY_FAST:
863 os << "NewSloppyFast";
865 case NEW_SLOPPY_SLOW:
866 os << "NewSloppySlow";
876 void RestParamAccessStub::PrintName(std::ostream& os) const { // NOLINT
877 os << "RestParamAccessStub_";
881 void CallFunctionStub::PrintName(std::ostream& os) const { // NOLINT
882 os << "CallFunctionStub_Args" << argc();
886 void CallConstructStub::PrintName(std::ostream& os) const { // NOLINT
887 os << "CallConstructStub";
888 if (RecordCallTarget()) os << "_Recording";
892 void ArrayConstructorStub::PrintName(std::ostream& os) const { // NOLINT
893 os << "ArrayConstructorStub";
894 switch (argument_count()) {
905 os << "_More_Than_One";
912 std::ostream& ArrayConstructorStubBase::BasePrintName(
913 std::ostream& os, // NOLINT
914 const char* name) const {
915 os << name << "_" << ElementsKindToString(elements_kind());
916 if (override_mode() == DISABLE_ALLOCATION_SITES) {
917 os << "_DISABLE_ALLOCATION_SITES";
923 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
924 Types new_types = types();
925 Types old_types = new_types;
926 bool to_boolean_value = new_types.UpdateStatus(object);
927 TraceTransition(old_types, new_types);
928 set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToByte()));
929 return to_boolean_value;
933 void ToBooleanStub::PrintState(std::ostream& os) const { // NOLINT
938 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) {
940 SimpleListPrinter p(os);
941 if (s.IsEmpty()) p.Add("None");
942 if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined");
943 if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool");
944 if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null");
945 if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi");
946 if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject");
947 if (s.Contains(ToBooleanStub::STRING)) p.Add("String");
948 if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol");
949 if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber");
954 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
955 if (object->IsUndefined()) {
958 } else if (object->IsBoolean()) {
960 return object->IsTrue();
961 } else if (object->IsNull()) {
964 } else if (object->IsSmi()) {
966 return Smi::cast(*object)->value() != 0;
967 } else if (object->IsSpecObject()) {
969 return !object->IsUndetectableObject();
970 } else if (object->IsString()) {
972 return !object->IsUndetectableObject() &&
973 String::cast(*object)->length() != 0;
974 } else if (object->IsSymbol()) {
977 } else if (object->IsHeapNumber()) {
978 DCHECK(!object->IsUndetectableObject());
980 double value = HeapNumber::cast(*object)->value();
981 return value != 0 && !std::isnan(value);
983 // We should never see an internal object at runtime here!
990 bool ToBooleanStub::Types::NeedsMap() const {
991 return Contains(ToBooleanStub::SPEC_OBJECT)
992 || Contains(ToBooleanStub::STRING)
993 || Contains(ToBooleanStub::SYMBOL)
994 || Contains(ToBooleanStub::HEAP_NUMBER);
998 bool ToBooleanStub::Types::CanBeUndetectable() const {
999 return Contains(ToBooleanStub::SPEC_OBJECT)
1000 || Contains(ToBooleanStub::STRING);
1004 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
1005 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
1006 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
1012 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
1013 intptr_t stack_pointer,
1015 FunctionEntryHook entry_hook = isolate->function_entry_hook();
1016 DCHECK(entry_hook != NULL);
1017 entry_hook(function, stack_pointer);
1021 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
1022 : PlatformCodeStub(isolate) {
1023 minor_key_ = ArgumentCountBits::encode(ANY);
1024 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1028 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
1030 : PlatformCodeStub(isolate) {
1031 if (argument_count == 0) {
1032 minor_key_ = ArgumentCountBits::encode(NONE);
1033 } else if (argument_count == 1) {
1034 minor_key_ = ArgumentCountBits::encode(ONE);
1035 } else if (argument_count >= 2) {
1036 minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
1040 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1044 InternalArrayConstructorStub::InternalArrayConstructorStub(
1045 Isolate* isolate) : PlatformCodeStub(isolate) {
1046 InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1050 } // namespace internal