deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / code-stubs.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/code-stubs.h"
6
7 #include <sstream>
8
9 #include "src/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
17 namespace v8 {
18 namespace internal {
19
20
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),
28       miss_handler_(),
29       has_miss_handler_(false) {
30   stub->InitializeDescriptor(this);
31 }
32
33
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),
40       miss_handler_(),
41       has_miss_handler_(false) {
42   CodeStub::InitializeDescriptor(isolate, stub_key, this);
43 }
44
45
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;
52 }
53
54
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;
63 }
64
65
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));
71     return true;
72   }
73   return false;
74 }
75
76
77 void CodeStub::RecordCodeGeneration(Handle<Code> code) {
78   std::ostringstream os;
79   os << *this;
80   PROFILE(isolate(),
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());
84 #ifdef DEBUG
85   code->VerifyEmbeddedObjects();
86 #endif
87 }
88
89
90 Code::Kind CodeStub::GetCodeKind() const {
91   return Code::STUB;
92 }
93
94
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);
100   return ic;
101 }
102
103
104 Handle<Code> PlatformCodeStub::GenerateCode() {
105   Factory* factory = isolate()->factory();
106
107   // Generate the new code.
108   MacroAssembler masm(isolate(), NULL, 256);
109
110   {
111     // Update the static counter each time a new code stub is generated.
112     isolate()->counters()->code_stubs()->Increment();
113
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);
119     Generate(&masm);
120   }
121
122   // Create the code object.
123   CodeDesc desc;
124   masm.GetCode(&desc);
125
126   // Copy the generated code into a heap object.
127   Code::Flags flags = Code::ComputeFlags(
128       GetCodeKind(),
129       GetICState(),
130       GetExtraICState(),
131       GetStubType());
132   Handle<Code> new_object = factory->NewCode(
133       desc, flags, masm.CodeObject(), NeedsImmovableCode());
134   return new_object;
135 }
136
137
138 Handle<Code> CodeStub::GetCode() {
139   Heap* heap = isolate()->heap();
140   Code* code;
141   if (UseSpecialCache() ? FindCodeInSpecialCache(&code)
142                         : FindCodeInCache(&code)) {
143     DCHECK(GetCodeKind() == code->kind());
144     return Handle<Code>(code);
145   }
146
147   {
148     HandleScope scope(isolate());
149
150     Handle<Code> new_object = GenerateCode();
151     new_object->set_stub_key(GetKey());
152     FinishCode(new_object);
153     RecordCodeGeneration(new_object);
154
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;
160       name << *this;
161       new_object->Disassemble(name.str().c_str(), os);
162       os << "\n";
163     }
164 #endif
165
166     if (UseSpecialCache()) {
167       AddToSpecialCache(new_object);
168     } else {
169       // Update the dictionary and the root in Heap.
170       Handle<UnseededNumberDictionary> dict =
171           UnseededNumberDictionary::AtNumberPut(
172               Handle<UnseededNumberDictionary>(heap->code_stubs()),
173               GetKey(),
174               new_object);
175       heap->public_set_code_stubs(*dict);
176     }
177     code = *new_object;
178   }
179
180   Activate(code);
181   DCHECK(!NeedsImmovableCode() ||
182          heap->lo_space()->Contains(code) ||
183          heap->code_space()->FirstPage()->Contains(code->address()));
184   return Handle<Code>(code, isolate());
185 }
186
187
188 const char* CodeStub::MajorName(CodeStub::Major major_key,
189                                 bool allow_unknown_keys) {
190   switch (major_key) {
191 #define DEF_CASE(name) case name: return #name "Stub";
192     CODE_STUB_LIST(DEF_CASE)
193 #undef DEF_CASE
194     case NoCache:
195       return "<NoCache>Stub";
196     case NUMBER_OF_IDS:
197       UNREACHABLE();
198       return NULL;
199   }
200   return NULL;
201 }
202
203
204 void CodeStub::PrintBaseName(std::ostream& os) const {  // NOLINT
205   os << MajorName(MajorKey(), false);
206 }
207
208
209 void CodeStub::PrintName(std::ostream& os) const {  // NOLINT
210   PrintBaseName(os);
211   PrintState(os);
212 }
213
214
215 void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
216                         DispatchedCall call) {
217   switch (MajorKeyFromKey(key)) {
218 #define DEF_CASE(NAME)             \
219   case NAME: {                     \
220     NAME##Stub stub(key, isolate); \
221     CodeStub* pstub = &stub;       \
222     call(pstub, value_out);        \
223     break;                         \
224   }
225     CODE_STUB_LIST(DEF_CASE)
226 #undef DEF_CASE
227     case NUMBER_OF_IDS:
228     case NoCache:
229       UNREACHABLE();
230       break;
231   }
232 }
233
234
235 static void InitializeDescriptorDispatchedCall(CodeStub* stub,
236                                                void** value_out) {
237   CodeStubDescriptor* descriptor_out =
238       reinterpret_cast<CodeStubDescriptor*>(value_out);
239   stub->InitializeDescriptor(descriptor_out);
240   descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
241 }
242
243
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);
248 }
249
250
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();
255 }
256
257
258 MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
259   HandleScope scope(isolate);
260   Handle<Code> code;
261   void** value_out = reinterpret_cast<void**>(&code);
262   Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
263   return scope.CloseAndEscape(code);
264 }
265
266
267 // static
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));
272     stub.GetCode();
273   }
274
275   // Generate special versions of the stub.
276   BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
277 }
278
279
280 void BinaryOpICStub::PrintState(std::ostream& os) const {  // NOLINT
281   os << state();
282 }
283
284
285 // static
286 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
287                                          const BinaryOpICState& state) {
288   BinaryOpICStub stub(isolate, state);
289   stub.GetCode();
290 }
291
292
293 // static
294 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
295   // Generate special versions of the stub.
296   BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
297 }
298
299
300 void BinaryOpICWithAllocationSiteStub::PrintState(
301     std::ostream& os) const {  // NOLINT
302   os << state();
303 }
304
305
306 // static
307 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
308     Isolate* isolate, const BinaryOpICState& state) {
309   if (state.CouldCreateAllocationMementos()) {
310     BinaryOpICWithAllocationSiteStub stub(isolate, state);
311     stub.GetCode();
312   }
313 }
314
315
316 void StringAddStub::PrintBaseName(std::ostream& os) const {  // NOLINT
317   os << "StringAddStub";
318   if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
319     os << "_CheckBoth";
320   } else if ((flags() & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
321     os << "_CheckLeft";
322   } else if ((flags() & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
323     os << "_CheckRight";
324   }
325   if (pretenure_flag() == TENURED) {
326     os << "_Tenured";
327   }
328 }
329
330
331 InlineCacheState CompareICStub::GetICState() const {
332   CompareICState::State state = Max(left(), right());
333   switch (state) {
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:
343       return MONOMORPHIC;
344     case CompareICState::GENERIC:
345       return ::v8::internal::GENERIC;
346   }
347   UNREACHABLE();
348   return ::v8::internal::UNINITIALIZED;
349 }
350
351
352 Condition CompareICStub::GetCondition() const {
353   return CompareIC::ComputeCondition(op());
354 }
355
356
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_,
362                               strict() ?
363                                   factory->strict_compare_ic_string() :
364                                   factory->compare_ic_string(),
365                               new_object);
366 }
367
368
369 bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
370   Factory* factory = isolate()->factory();
371   Code::Flags flags = Code::ComputeFlags(
372       GetCodeKind(),
373       UNINITIALIZED);
374   DCHECK(op() == Token::EQ || op() == Token::EQ_STRICT);
375   Handle<Object> probe(
376       known_map_->FindInCodeCache(
377         strict() ?
378             *factory->strict_compare_ic_string() :
379             *factory->compare_ic_string(),
380         flags),
381       isolate());
382   if (probe->IsCode()) {
383     *code_out = Code::cast(*probe);
384 #ifdef DEBUG
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());
390 #endif
391     return true;
392   }
393   return false;
394 }
395
396
397 void CompareICStub::Generate(MacroAssembler* masm) {
398   switch (state()) {
399     case CompareICState::UNINITIALIZED:
400       GenerateMiss(masm);
401       break;
402     case CompareICState::SMI:
403       GenerateSmis(masm);
404       break;
405     case CompareICState::NUMBER:
406       GenerateNumbers(masm);
407       break;
408     case CompareICState::STRING:
409       GenerateStrings(masm);
410       break;
411     case CompareICState::INTERNALIZED_STRING:
412       GenerateInternalizedStrings(masm);
413       break;
414     case CompareICState::UNIQUE_NAME:
415       GenerateUniqueNames(masm);
416       break;
417     case CompareICState::OBJECT:
418       GenerateObjects(masm);
419       break;
420     case CompareICState::KNOWN_OBJECT:
421       DCHECK(*known_map_ != NULL);
422       GenerateKnownObjects(masm);
423       break;
424     case CompareICState::GENERIC:
425       GenerateGeneric(masm);
426       break;
427   }
428 }
429
430
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()) {
442     state.RemoveAll();
443     state.Add(GENERIC);
444   } else if (IsMonomorphic()) {
445     state.RemoveAll();
446     state.Add(GENERIC);
447   } else {
448     state.Add(MONOMORPHIC_MAP);
449   }
450   TraceTransition(old_state, state);
451   set_sub_minor_key(TypesBits::update(sub_minor_key(), state.ToIntegral()));
452 }
453
454
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.
459   DCHECK(from != to);
460   if (!FLAG_trace_ic) return;
461   OFStream os(stdout);
462   os << "[";
463   PrintBaseName(os);
464   os << ": " << from << "=>" << to << "]" << std::endl;
465 }
466
467
468 void CompareNilICStub::PrintBaseName(std::ostream& os) const {  // NOLINT
469   CodeStub::PrintBaseName(os);
470   os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
471 }
472
473
474 void CompareNilICStub::PrintState(std::ostream& os) const {  // NOLINT
475   os << state();
476 }
477
478
479 // TODO(svenpanne) Make this a real infix_ostream_iterator.
480 class SimpleListPrinter {
481  public:
482   explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {}
483
484   void Add(const char* s) {
485     if (first_) {
486       first_ = false;
487     } else {
488       os_ << ",";
489     }
490     os_ << s;
491   }
492
493  private:
494   std::ostream& os_;
495   bool first_;
496 };
497
498
499 std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s) {
500   os << "(";
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");
507   return os << ")";
508 }
509
510
511 Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
512   State state = this->state();
513   if (state.Contains(CompareNilICStub::GENERIC)) return Type::Any(zone);
514
515   Type* result = Type::None(zone);
516   if (state.Contains(CompareNilICStub::UNDEFINED)) {
517     result = Type::Union(result, Type::Undefined(zone), zone);
518   }
519   if (state.Contains(CompareNilICStub::NULL_TYPE)) {
520     result = Type::Union(result, Type::Null(zone), zone);
521   }
522   if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
523     Type* type =
524         map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
525     result = Type::Union(result, type, zone);
526   }
527
528   return result;
529 }
530
531
532 Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
533   Type* output_type = GetType(zone, map);
534   Type* nil_type =
535       nil_value() == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
536   return Type::Union(output_type, nil_type, zone);
537 }
538
539
540 void CallIC_ArrayStub::PrintState(std::ostream& os) const {  // NOLINT
541   os << state() << " (Array)";
542 }
543
544
545 void CallICStub::PrintState(std::ostream& os) const {  // NOLINT
546   os << state();
547 }
548
549
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";
555 }
556
557
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);
563 }
564
565
566 void LoadFastElementStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
567   descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
568 }
569
570
571 void LoadDictionaryElementStub::InitializeDescriptor(
572     CodeStubDescriptor* descriptor) {
573   descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
574 }
575
576
577 void KeyedLoadGenericStub::InitializeDescriptor(
578     CodeStubDescriptor* descriptor) {
579   descriptor->Initialize(
580       Runtime::FunctionForId(Runtime::kKeyedGetProperty)->entry);
581 }
582
583
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));
589   }
590 }
591
592
593 CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() {
594   if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
595     if (FLAG_vector_ics) {
596       return VectorLoadICDescriptor(isolate());
597     }
598     return LoadDescriptor(isolate());
599   } else {
600     DCHECK_EQ(Code::STORE_IC, kind());
601     return StoreDescriptor(isolate());
602   }
603 }
604
605
606 void StoreFastElementStub::InitializeDescriptor(
607     CodeStubDescriptor* descriptor) {
608   descriptor->Initialize(FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
609 }
610
611
612 void ElementsTransitionAndStoreStub::InitializeDescriptor(
613     CodeStubDescriptor* descriptor) {
614   descriptor->Initialize(FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss));
615 }
616
617
618 CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor() {
619   return StoreTransitionDescriptor(isolate());
620 }
621
622
623 void MegamorphicLoadStub::InitializeDescriptor(CodeStubDescriptor* d) {}
624
625
626 void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
627   descriptor->Initialize(
628       Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry);
629 }
630
631
632 void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
633
634
635 void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
636   NumberToStringDescriptor call_descriptor(isolate());
637   descriptor->Initialize(
638       Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry);
639 }
640
641
642 void FastCloneShallowArrayStub::InitializeDescriptor(
643     CodeStubDescriptor* descriptor) {
644   FastCloneShallowArrayDescriptor call_descriptor(isolate());
645   descriptor->Initialize(
646       Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
647 }
648
649
650 void FastCloneShallowObjectStub::InitializeDescriptor(
651     CodeStubDescriptor* descriptor) {
652   FastCloneShallowObjectDescriptor call_descriptor(isolate());
653   descriptor->Initialize(
654       Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
655 }
656
657
658 void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
659
660
661 void CreateWeakCellStub::InitializeDescriptor(CodeStubDescriptor* d) {}
662
663
664 void RegExpConstructResultStub::InitializeDescriptor(
665     CodeStubDescriptor* descriptor) {
666   descriptor->Initialize(
667       Runtime::FunctionForId(Runtime::kRegExpConstructResultRT)->entry);
668 }
669
670
671 void TransitionElementsKindStub::InitializeDescriptor(
672     CodeStubDescriptor* descriptor) {
673   descriptor->Initialize(
674       Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
675 }
676
677
678 void AllocateHeapNumberStub::InitializeDescriptor(
679     CodeStubDescriptor* descriptor) {
680   descriptor->Initialize(
681       Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry);
682 }
683
684
685 void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
686   descriptor->Initialize(FUNCTION_ADDR(CompareNilIC_Miss));
687   descriptor->SetMissHandler(
688       ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate()));
689 }
690
691
692 void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
693   descriptor->Initialize(FUNCTION_ADDR(ToBooleanIC_Miss));
694   descriptor->SetMissHandler(
695       ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate()));
696 }
697
698
699 void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
700   descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_Miss));
701   descriptor->SetMissHandler(
702       ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate()));
703 }
704
705
706 void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
707     CodeStubDescriptor* descriptor) {
708   descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite));
709 }
710
711
712 void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
713   descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAddRT)->entry);
714 }
715
716
717 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
718   CreateAllocationSiteStub stub(isolate);
719   stub.GetCode();
720 }
721
722
723 void CreateWeakCellStub::GenerateAheadOfTime(Isolate* isolate) {
724   CreateWeakCellStub stub(isolate);
725   stub.GetCode();
726 }
727
728
729 void StoreElementStub::Generate(MacroAssembler* masm) {
730   switch (elements_kind()) {
731     case FAST_ELEMENTS:
732     case FAST_HOLEY_ELEMENTS:
733     case FAST_SMI_ELEMENTS:
734     case FAST_HOLEY_SMI_ELEMENTS:
735     case FAST_DOUBLE_ELEMENTS:
736     case FAST_HOLEY_DOUBLE_ELEMENTS:
737 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
738     case EXTERNAL_##TYPE##_ELEMENTS:                    \
739     case TYPE##_ELEMENTS:
740
741     TYPED_ARRAYS(TYPED_ARRAY_CASE)
742 #undef TYPED_ARRAY_CASE
743       UNREACHABLE();
744       break;
745     case DICTIONARY_ELEMENTS:
746       ElementHandlerCompiler::GenerateStoreSlow(masm);
747       break;
748     case SLOPPY_ARGUMENTS_ELEMENTS:
749       UNREACHABLE();
750       break;
751   }
752 }
753
754
755 void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
756   switch (type()) {
757     case READ_ELEMENT:
758       GenerateReadElement(masm);
759       break;
760     case NEW_SLOPPY_FAST:
761       GenerateNewSloppyFast(masm);
762       break;
763     case NEW_SLOPPY_SLOW:
764       GenerateNewSloppySlow(masm);
765       break;
766     case NEW_STRICT:
767       GenerateNewStrict(masm);
768       break;
769   }
770 }
771
772
773 void RestParamAccessStub::Generate(MacroAssembler* masm) {
774   GenerateNew(masm);
775 }
776
777
778 void ArgumentsAccessStub::PrintName(std::ostream& os) const {  // NOLINT
779   os << "ArgumentsAccessStub_";
780   switch (type()) {
781     case READ_ELEMENT:
782       os << "ReadElement";
783       break;
784     case NEW_SLOPPY_FAST:
785       os << "NewSloppyFast";
786       break;
787     case NEW_SLOPPY_SLOW:
788       os << "NewSloppySlow";
789       break;
790     case NEW_STRICT:
791       os << "NewStrict";
792       break;
793   }
794   return;
795 }
796
797
798 void RestParamAccessStub::PrintName(std::ostream& os) const {  // NOLINT
799   os << "RestParamAccessStub_";
800 }
801
802
803 void CallFunctionStub::PrintName(std::ostream& os) const {  // NOLINT
804   os << "CallFunctionStub_Args" << argc();
805 }
806
807
808 void CallConstructStub::PrintName(std::ostream& os) const {  // NOLINT
809   os << "CallConstructStub";
810   if (RecordCallTarget()) os << "_Recording";
811 }
812
813
814 void ArrayConstructorStub::PrintName(std::ostream& os) const {  // NOLINT
815   os << "ArrayConstructorStub";
816   switch (argument_count()) {
817     case ANY:
818       os << "_Any";
819       break;
820     case NONE:
821       os << "_None";
822       break;
823     case ONE:
824       os << "_One";
825       break;
826     case MORE_THAN_ONE:
827       os << "_More_Than_One";
828       break;
829   }
830   return;
831 }
832
833
834 std::ostream& ArrayConstructorStubBase::BasePrintName(
835     std::ostream& os,  // NOLINT
836     const char* name) const {
837   os << name << "_" << ElementsKindToString(elements_kind());
838   if (override_mode() == DISABLE_ALLOCATION_SITES) {
839     os << "_DISABLE_ALLOCATION_SITES";
840   }
841   return os;
842 }
843
844
845 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
846   Types new_types = types();
847   Types old_types = new_types;
848   bool to_boolean_value = new_types.UpdateStatus(object);
849   TraceTransition(old_types, new_types);
850   set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToByte()));
851   return to_boolean_value;
852 }
853
854
855 void ToBooleanStub::PrintState(std::ostream& os) const {  // NOLINT
856   os << types();
857 }
858
859
860 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) {
861   os << "(";
862   SimpleListPrinter p(os);
863   if (s.IsEmpty()) p.Add("None");
864   if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined");
865   if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool");
866   if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null");
867   if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi");
868   if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject");
869   if (s.Contains(ToBooleanStub::STRING)) p.Add("String");
870   if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol");
871   if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber");
872   return os << ")";
873 }
874
875
876 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
877   if (object->IsUndefined()) {
878     Add(UNDEFINED);
879     return false;
880   } else if (object->IsBoolean()) {
881     Add(BOOLEAN);
882     return object->IsTrue();
883   } else if (object->IsNull()) {
884     Add(NULL_TYPE);
885     return false;
886   } else if (object->IsSmi()) {
887     Add(SMI);
888     return Smi::cast(*object)->value() != 0;
889   } else if (object->IsSpecObject()) {
890     Add(SPEC_OBJECT);
891     return !object->IsUndetectableObject();
892   } else if (object->IsString()) {
893     Add(STRING);
894     return !object->IsUndetectableObject() &&
895         String::cast(*object)->length() != 0;
896   } else if (object->IsSymbol()) {
897     Add(SYMBOL);
898     return true;
899   } else if (object->IsHeapNumber()) {
900     DCHECK(!object->IsUndetectableObject());
901     Add(HEAP_NUMBER);
902     double value = HeapNumber::cast(*object)->value();
903     return value != 0 && !std::isnan(value);
904   } else {
905     // We should never see an internal object at runtime here!
906     UNREACHABLE();
907     return true;
908   }
909 }
910
911
912 bool ToBooleanStub::Types::NeedsMap() const {
913   return Contains(ToBooleanStub::SPEC_OBJECT)
914       || Contains(ToBooleanStub::STRING)
915       || Contains(ToBooleanStub::SYMBOL)
916       || Contains(ToBooleanStub::HEAP_NUMBER);
917 }
918
919
920 bool ToBooleanStub::Types::CanBeUndetectable() const {
921   return Contains(ToBooleanStub::SPEC_OBJECT)
922       || Contains(ToBooleanStub::STRING);
923 }
924
925
926 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
927   StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
928   StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
929   stub1.GetCode();
930   stub2.GetCode();
931 }
932
933
934 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
935                                                intptr_t stack_pointer,
936                                                Isolate* isolate) {
937   FunctionEntryHook entry_hook = isolate->function_entry_hook();
938   DCHECK(entry_hook != NULL);
939   entry_hook(function, stack_pointer);
940 }
941
942
943 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
944     : PlatformCodeStub(isolate) {
945   minor_key_ = ArgumentCountBits::encode(ANY);
946   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
947 }
948
949
950 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
951                                            int argument_count)
952     : PlatformCodeStub(isolate) {
953   if (argument_count == 0) {
954     minor_key_ = ArgumentCountBits::encode(NONE);
955   } else if (argument_count == 1) {
956     minor_key_ = ArgumentCountBits::encode(ONE);
957   } else if (argument_count >= 2) {
958     minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
959   } else {
960     UNREACHABLE();
961   }
962   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
963 }
964
965
966 InternalArrayConstructorStub::InternalArrayConstructorStub(
967     Isolate* isolate) : PlatformCodeStub(isolate) {
968   InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
969 }
970
971
972 } }  // namespace v8::internal