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