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