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