3e1b54835ed7f5cf12295eb188d99dc8fb1d6806
[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   }
328   UNREACHABLE();
329   return os;
330 }
331
332
333 void StringAddStub::PrintBaseName(std::ostream& os) const {  // NOLINT
334   os << "StringAddStub_" << flags() << "_" << pretenure_flag();
335 }
336
337
338 void StringAddTFStub::PrintBaseName(std::ostream& os) const {  // NOLINT
339   os << "StringAddTFStub_" << flags() << "_" << pretenure_flag();
340 }
341
342
343 InlineCacheState CompareICStub::GetICState() const {
344   CompareICState::State state = Max(left(), right());
345   switch (state) {
346     case CompareICState::UNINITIALIZED:
347       return ::v8::internal::UNINITIALIZED;
348     case CompareICState::SMI:
349     case CompareICState::NUMBER:
350     case CompareICState::INTERNALIZED_STRING:
351     case CompareICState::STRING:
352     case CompareICState::UNIQUE_NAME:
353     case CompareICState::OBJECT:
354     case CompareICState::KNOWN_OBJECT:
355       return MONOMORPHIC;
356     case CompareICState::GENERIC:
357       return ::v8::internal::GENERIC;
358   }
359   UNREACHABLE();
360   return ::v8::internal::UNINITIALIZED;
361 }
362
363
364 Condition CompareICStub::GetCondition() const {
365   return CompareIC::ComputeCondition(op());
366 }
367
368
369 void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
370   DCHECK(*known_map_ != NULL);
371   Isolate* isolate = new_object->GetIsolate();
372   Factory* factory = isolate->factory();
373   return Map::UpdateCodeCache(known_map_,
374                               strict() ?
375                                   factory->strict_compare_ic_string() :
376                                   factory->compare_ic_string(),
377                               new_object);
378 }
379
380
381 bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
382   Factory* factory = isolate()->factory();
383   Code::Flags flags = Code::ComputeFlags(
384       GetCodeKind(),
385       UNINITIALIZED);
386   DCHECK(op() == Token::EQ || op() == Token::EQ_STRICT);
387   Handle<Object> probe(
388       known_map_->FindInCodeCache(
389         strict() ?
390             *factory->strict_compare_ic_string() :
391             *factory->compare_ic_string(),
392         flags),
393       isolate());
394   if (probe->IsCode()) {
395     *code_out = Code::cast(*probe);
396 #ifdef DEBUG
397     CompareICStub decode((*code_out)->stub_key(), isolate());
398     DCHECK(op() == decode.op());
399     DCHECK(left() == decode.left());
400     DCHECK(right() == decode.right());
401     DCHECK(state() == decode.state());
402 #endif
403     return true;
404   }
405   return false;
406 }
407
408
409 void CompareICStub::Generate(MacroAssembler* masm) {
410   switch (state()) {
411     case CompareICState::UNINITIALIZED:
412       GenerateMiss(masm);
413       break;
414     case CompareICState::SMI:
415       GenerateSmis(masm);
416       break;
417     case CompareICState::NUMBER:
418       GenerateNumbers(masm);
419       break;
420     case CompareICState::STRING:
421       GenerateStrings(masm);
422       break;
423     case CompareICState::INTERNALIZED_STRING:
424       GenerateInternalizedStrings(masm);
425       break;
426     case CompareICState::UNIQUE_NAME:
427       GenerateUniqueNames(masm);
428       break;
429     case CompareICState::OBJECT:
430       GenerateObjects(masm);
431       break;
432     case CompareICState::KNOWN_OBJECT:
433       DCHECK(*known_map_ != NULL);
434       GenerateKnownObjects(masm);
435       break;
436     case CompareICState::GENERIC:
437       GenerateGeneric(masm);
438       break;
439   }
440 }
441
442
443 void CompareNilICStub::UpdateStatus(Handle<Object> object) {
444   State state = this->state();
445   DCHECK(!state.Contains(GENERIC));
446   State old_state = state;
447   if (object->IsNull()) {
448     state.Add(NULL_TYPE);
449   } else if (object->IsUndefined()) {
450     state.Add(UNDEFINED);
451   } else if (object->IsUndetectableObject() ||
452              object->IsOddball() ||
453              !object->IsHeapObject()) {
454     state.RemoveAll();
455     state.Add(GENERIC);
456   } else if (IsMonomorphic()) {
457     state.RemoveAll();
458     state.Add(GENERIC);
459   } else {
460     state.Add(MONOMORPHIC_MAP);
461   }
462   TraceTransition(old_state, state);
463   set_sub_minor_key(TypesBits::update(sub_minor_key(), state.ToIntegral()));
464 }
465
466
467 namespace {
468
469 Handle<JSFunction> GetFunction(Isolate* isolate, const char* name) {
470   v8::ExtensionConfiguration no_extensions;
471   MaybeHandle<Object> fun = Object::GetProperty(
472       isolate, isolate->factory()->code_stub_exports_object(), name);
473   Handle<JSFunction> function = Handle<JSFunction>::cast(fun.ToHandleChecked());
474   DCHECK(!function->IsUndefined() &&
475          "JavaScript implementation of stub not found");
476   return function;
477 }
478 }  // namespace
479
480
481 Handle<Code> TurboFanCodeStub::GenerateCode() {
482   // Get the outer ("stub generator") function.
483   const char* name = CodeStub::MajorName(MajorKey());
484   Handle<JSFunction> outer = GetFunction(isolate(), name);
485   DCHECK_EQ(2, outer->shared()->length());
486
487   // Invoke the outer function to get the stub itself.
488   Factory* factory = isolate()->factory();
489   Handle<Object> call_conv = factory->InternalizeUtf8String(name);
490   Handle<Object> minor_key = factory->NewNumber(MinorKey());
491   Handle<Object> args[] = {call_conv, minor_key};
492   MaybeHandle<Object> result =
493       Execution::Call(isolate(), outer, factory->undefined_value(), 2, args);
494   Handle<JSFunction> inner = Handle<JSFunction>::cast(result.ToHandleChecked());
495   // Just to make sure nobody calls this...
496   inner->set_code(isolate()->builtins()->builtin(Builtins::kIllegal));
497
498   return Compiler::GetStubCode(inner, this).ToHandleChecked();
499 }
500
501
502 template<class StateType>
503 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
504   // Note: Although a no-op transition is semantically OK, it is hinting at a
505   // bug somewhere in our state transition machinery.
506   DCHECK(from != to);
507   if (!FLAG_trace_ic) return;
508   OFStream os(stdout);
509   os << "[";
510   PrintBaseName(os);
511   os << ": " << from << "=>" << to << "]" << std::endl;
512 }
513
514
515 void CompareNilICStub::PrintBaseName(std::ostream& os) const {  // NOLINT
516   CodeStub::PrintBaseName(os);
517   os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
518 }
519
520
521 void CompareNilICStub::PrintState(std::ostream& os) const {  // NOLINT
522   os << state();
523 }
524
525
526 // TODO(svenpanne) Make this a real infix_ostream_iterator.
527 class SimpleListPrinter {
528  public:
529   explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {}
530
531   void Add(const char* s) {
532     if (first_) {
533       first_ = false;
534     } else {
535       os_ << ",";
536     }
537     os_ << s;
538   }
539
540  private:
541   std::ostream& os_;
542   bool first_;
543 };
544
545
546 std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s) {
547   os << "(";
548   SimpleListPrinter p(os);
549   if (s.IsEmpty()) p.Add("None");
550   if (s.Contains(CompareNilICStub::UNDEFINED)) p.Add("Undefined");
551   if (s.Contains(CompareNilICStub::NULL_TYPE)) p.Add("Null");
552   if (s.Contains(CompareNilICStub::MONOMORPHIC_MAP)) p.Add("MonomorphicMap");
553   if (s.Contains(CompareNilICStub::GENERIC)) p.Add("Generic");
554   return os << ")";
555 }
556
557
558 Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
559   State state = this->state();
560   if (state.Contains(CompareNilICStub::GENERIC)) return Type::Any(zone);
561
562   Type* result = Type::None(zone);
563   if (state.Contains(CompareNilICStub::UNDEFINED)) {
564     result = Type::Union(result, Type::Undefined(zone), zone);
565   }
566   if (state.Contains(CompareNilICStub::NULL_TYPE)) {
567     result = Type::Union(result, Type::Null(zone), zone);
568   }
569   if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
570     Type* type =
571         map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
572     result = Type::Union(result, type, zone);
573   }
574
575   return result;
576 }
577
578
579 Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
580   Type* output_type = GetType(zone, map);
581   Type* nil_type =
582       nil_value() == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
583   return Type::Union(output_type, nil_type, zone);
584 }
585
586
587 void CallICStub::PrintState(std::ostream& os) const {  // NOLINT
588   os << state();
589 }
590
591
592 void JSEntryStub::FinishCode(Handle<Code> code) {
593   Handle<FixedArray> handler_table =
594       code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
595   handler_table->set(0, Smi::FromInt(handler_offset_));
596   code->set_handler_table(*handler_table);
597 }
598
599
600 void LoadDictionaryElementStub::InitializeDescriptor(
601     CodeStubDescriptor* descriptor) {
602   descriptor->Initialize(
603       FUNCTION_ADDR(Runtime_KeyedLoadIC_MissFromStubFailure));
604 }
605
606
607 void KeyedLoadGenericStub::InitializeDescriptor(
608     CodeStubDescriptor* descriptor) {
609   descriptor->Initialize(
610       Runtime::FunctionForId(is_strong(language_mode())
611                                  ? Runtime::kKeyedGetPropertyStrong
612                                  : Runtime::kKeyedGetProperty)->entry);
613 }
614
615
616 void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
617   if (kind() == Code::STORE_IC) {
618     descriptor->Initialize(FUNCTION_ADDR(Runtime_StoreIC_MissFromStubFailure));
619   } else if (kind() == Code::KEYED_LOAD_IC) {
620     descriptor->Initialize(
621         FUNCTION_ADDR(Runtime_KeyedLoadIC_MissFromStubFailure));
622   } else if (kind() == Code::KEYED_STORE_IC) {
623     descriptor->Initialize(
624         FUNCTION_ADDR(Runtime_KeyedStoreIC_MissFromStubFailure));
625   }
626 }
627
628
629 CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() const {
630   if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
631     return LoadWithVectorDescriptor(isolate());
632   } else {
633     DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC);
634     return FLAG_vector_stores ? VectorStoreICDescriptor(isolate())
635                               : StoreDescriptor(isolate());
636   }
637 }
638
639
640 void StoreFastElementStub::InitializeDescriptor(
641     CodeStubDescriptor* descriptor) {
642   descriptor->Initialize(
643       FUNCTION_ADDR(Runtime_KeyedStoreIC_MissFromStubFailure));
644 }
645
646
647 void ElementsTransitionAndStoreStub::InitializeDescriptor(
648     CodeStubDescriptor* descriptor) {
649   descriptor->Initialize(
650       FUNCTION_ADDR(Runtime_ElementsTransitionAndStoreIC_Miss));
651 }
652
653
654 void ToObjectStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
655   descriptor->Initialize(Runtime::FunctionForId(Runtime::kToObject)->entry);
656 }
657
658
659 CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor()
660     const {
661   if (FLAG_vector_stores) {
662     return VectorStoreTransitionDescriptor(isolate());
663   }
664   return StoreTransitionDescriptor(isolate());
665 }
666
667
668 CallInterfaceDescriptor
669 ElementsTransitionAndStoreStub::GetCallInterfaceDescriptor() const {
670   if (FLAG_vector_stores) {
671     return VectorStoreTransitionDescriptor(isolate());
672   }
673   return StoreTransitionDescriptor(isolate());
674 }
675
676
677 void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
678   descriptor->Initialize(Runtime::FunctionForId(Runtime::kNewClosure)->entry);
679 }
680
681
682 void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
683
684
685 void TypeofStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {}
686
687
688 void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
689   NumberToStringDescriptor call_descriptor(isolate());
690   descriptor->Initialize(
691       Runtime::FunctionForId(Runtime::kNumberToString)->entry);
692 }
693
694
695 void FastCloneShallowArrayStub::InitializeDescriptor(
696     CodeStubDescriptor* descriptor) {
697   FastCloneShallowArrayDescriptor call_descriptor(isolate());
698   descriptor->Initialize(
699       Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
700 }
701
702
703 void FastCloneShallowObjectStub::InitializeDescriptor(
704     CodeStubDescriptor* descriptor) {
705   FastCloneShallowObjectDescriptor call_descriptor(isolate());
706   descriptor->Initialize(
707       Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
708 }
709
710
711 void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
712
713
714 void CreateWeakCellStub::InitializeDescriptor(CodeStubDescriptor* d) {}
715
716
717 void RegExpConstructResultStub::InitializeDescriptor(
718     CodeStubDescriptor* descriptor) {
719   descriptor->Initialize(
720       Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry);
721 }
722
723
724 void TransitionElementsKindStub::InitializeDescriptor(
725     CodeStubDescriptor* descriptor) {
726   descriptor->Initialize(
727       Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
728 }
729
730
731 void AllocateHeapNumberStub::InitializeDescriptor(
732     CodeStubDescriptor* descriptor) {
733   descriptor->Initialize(
734       Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry);
735 }
736
737
738 void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
739   descriptor->Initialize(FUNCTION_ADDR(Runtime_CompareNilIC_Miss));
740   descriptor->SetMissHandler(ExternalReference(
741       Runtime::FunctionForId(Runtime::kCompareNilIC_Miss), isolate()));
742 }
743
744
745 void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
746   descriptor->Initialize(FUNCTION_ADDR(Runtime_ToBooleanIC_Miss));
747   descriptor->SetMissHandler(ExternalReference(
748       Runtime::FunctionForId(Runtime::kToBooleanIC_Miss), isolate()));
749 }
750
751
752 void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
753   descriptor->Initialize(FUNCTION_ADDR(Runtime_BinaryOpIC_Miss));
754   descriptor->SetMissHandler(ExternalReference(
755       Runtime::FunctionForId(Runtime::kBinaryOpIC_Miss), isolate()));
756 }
757
758
759 void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
760     CodeStubDescriptor* descriptor) {
761   descriptor->Initialize(
762       FUNCTION_ADDR(Runtime_BinaryOpIC_MissWithAllocationSite));
763 }
764
765
766 void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
767   descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAdd)->entry);
768 }
769
770
771 void GrowArrayElementsStub::InitializeDescriptor(
772     CodeStubDescriptor* descriptor) {
773   descriptor->Initialize(
774       Runtime::FunctionForId(Runtime::kGrowArrayElements)->entry);
775 }
776
777
778 void TypeofStub::GenerateAheadOfTime(Isolate* isolate) {
779   TypeofStub stub(isolate);
780   stub.GetCode();
781 }
782
783
784 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
785   CreateAllocationSiteStub stub(isolate);
786   stub.GetCode();
787 }
788
789
790 void CreateWeakCellStub::GenerateAheadOfTime(Isolate* isolate) {
791   CreateWeakCellStub stub(isolate);
792   stub.GetCode();
793 }
794
795
796 void StoreElementStub::Generate(MacroAssembler* masm) {
797   switch (elements_kind()) {
798     case FAST_ELEMENTS:
799     case FAST_HOLEY_ELEMENTS:
800     case FAST_SMI_ELEMENTS:
801     case FAST_HOLEY_SMI_ELEMENTS:
802     case FAST_DOUBLE_ELEMENTS:
803     case FAST_HOLEY_DOUBLE_ELEMENTS:
804 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
805     case TYPE##_ELEMENTS:
806
807     TYPED_ARRAYS(TYPED_ARRAY_CASE)
808 #undef TYPED_ARRAY_CASE
809       UNREACHABLE();
810       break;
811     case DICTIONARY_ELEMENTS:
812       ElementHandlerCompiler::GenerateStoreSlow(masm);
813       break;
814     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
815     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
816       UNREACHABLE();
817       break;
818   }
819 }
820
821
822 // static
823 void StoreFastElementStub::GenerateAheadOfTime(Isolate* isolate) {
824   StoreFastElementStub(isolate, false, FAST_HOLEY_ELEMENTS, STANDARD_STORE)
825       .GetCode();
826   StoreFastElementStub(isolate, false, FAST_HOLEY_ELEMENTS,
827                        STORE_AND_GROW_NO_TRANSITION).GetCode();
828   for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
829     ElementsKind kind = static_cast<ElementsKind>(i);
830     StoreFastElementStub(isolate, true, kind, STANDARD_STORE).GetCode();
831     StoreFastElementStub(isolate, true, kind, STORE_AND_GROW_NO_TRANSITION)
832         .GetCode();
833   }
834 }
835
836
837 void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
838   switch (type()) {
839     case READ_ELEMENT:
840       GenerateReadElement(masm);
841       break;
842     case NEW_SLOPPY_FAST:
843       GenerateNewSloppyFast(masm);
844       break;
845     case NEW_SLOPPY_SLOW:
846       GenerateNewSloppySlow(masm);
847       break;
848     case NEW_STRICT:
849       GenerateNewStrict(masm);
850       break;
851   }
852 }
853
854
855 void ArgumentsAccessStub::PrintName(std::ostream& os) const {  // NOLINT
856   os << "ArgumentsAccessStub_";
857   switch (type()) {
858     case READ_ELEMENT:
859       os << "ReadElement";
860       break;
861     case NEW_SLOPPY_FAST:
862       os << "NewSloppyFast";
863       break;
864     case NEW_SLOPPY_SLOW:
865       os << "NewSloppySlow";
866       break;
867     case NEW_STRICT:
868       os << "NewStrict";
869       break;
870   }
871   return;
872 }
873
874
875 void CallFunctionStub::PrintName(std::ostream& os) const {  // NOLINT
876   os << "CallFunctionStub_Args" << argc();
877 }
878
879
880 void CallConstructStub::PrintName(std::ostream& os) const {  // NOLINT
881   os << "CallConstructStub";
882   if (RecordCallTarget()) os << "_Recording";
883 }
884
885
886 void ArrayConstructorStub::PrintName(std::ostream& os) const {  // NOLINT
887   os << "ArrayConstructorStub";
888   switch (argument_count()) {
889     case ANY:
890       os << "_Any";
891       break;
892     case NONE:
893       os << "_None";
894       break;
895     case ONE:
896       os << "_One";
897       break;
898     case MORE_THAN_ONE:
899       os << "_More_Than_One";
900       break;
901   }
902   return;
903 }
904
905
906 std::ostream& ArrayConstructorStubBase::BasePrintName(
907     std::ostream& os,  // NOLINT
908     const char* name) const {
909   os << name << "_" << ElementsKindToString(elements_kind());
910   if (override_mode() == DISABLE_ALLOCATION_SITES) {
911     os << "_DISABLE_ALLOCATION_SITES";
912   }
913   return os;
914 }
915
916
917 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
918   Types new_types = types();
919   Types old_types = new_types;
920   bool to_boolean_value = new_types.UpdateStatus(object);
921   TraceTransition(old_types, new_types);
922   set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToIntegral()));
923   return to_boolean_value;
924 }
925
926
927 void ToBooleanStub::PrintState(std::ostream& os) const {  // NOLINT
928   os << types();
929 }
930
931
932 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& s) {
933   os << "(";
934   SimpleListPrinter p(os);
935   if (s.IsEmpty()) p.Add("None");
936   if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined");
937   if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool");
938   if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null");
939   if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi");
940   if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject");
941   if (s.Contains(ToBooleanStub::STRING)) p.Add("String");
942   if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol");
943   if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber");
944   if (s.Contains(ToBooleanStub::SIMD_VALUE)) p.Add("SimdValue");
945   return os << ")";
946 }
947
948
949 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
950   if (object->IsUndefined()) {
951     Add(UNDEFINED);
952     return false;
953   } else if (object->IsBoolean()) {
954     Add(BOOLEAN);
955     return object->IsTrue();
956   } else if (object->IsNull()) {
957     Add(NULL_TYPE);
958     return false;
959   } else if (object->IsSmi()) {
960     Add(SMI);
961     return Smi::cast(*object)->value() != 0;
962   } else if (object->IsSpecObject()) {
963     Add(SPEC_OBJECT);
964     return !object->IsUndetectableObject();
965   } else if (object->IsString()) {
966     Add(STRING);
967     return !object->IsUndetectableObject() &&
968         String::cast(*object)->length() != 0;
969   } else if (object->IsSymbol()) {
970     Add(SYMBOL);
971     return true;
972   } else if (object->IsHeapNumber()) {
973     DCHECK(!object->IsUndetectableObject());
974     Add(HEAP_NUMBER);
975     double value = HeapNumber::cast(*object)->value();
976     return value != 0 && !std::isnan(value);
977   } else if (object->IsSimd128Value()) {
978     Add(SIMD_VALUE);
979     return true;
980   } else {
981     // We should never see an internal object at runtime here!
982     UNREACHABLE();
983     return true;
984   }
985 }
986
987
988 bool ToBooleanStub::Types::NeedsMap() const {
989   return Contains(ToBooleanStub::SPEC_OBJECT) ||
990          Contains(ToBooleanStub::STRING) || Contains(ToBooleanStub::SYMBOL) ||
991          Contains(ToBooleanStub::HEAP_NUMBER) ||
992          Contains(ToBooleanStub::SIMD_VALUE);
993 }
994
995
996 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
997   StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
998   StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
999   stub1.GetCode();
1000   stub2.GetCode();
1001 }
1002
1003
1004 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
1005                                                intptr_t stack_pointer,
1006                                                Isolate* isolate) {
1007   FunctionEntryHook entry_hook = isolate->function_entry_hook();
1008   DCHECK(entry_hook != NULL);
1009   entry_hook(function, stack_pointer);
1010 }
1011
1012
1013 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
1014     : PlatformCodeStub(isolate) {
1015   minor_key_ = ArgumentCountBits::encode(ANY);
1016   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1017 }
1018
1019
1020 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
1021                                            int argument_count)
1022     : PlatformCodeStub(isolate) {
1023   if (argument_count == 0) {
1024     minor_key_ = ArgumentCountBits::encode(NONE);
1025   } else if (argument_count == 1) {
1026     minor_key_ = ArgumentCountBits::encode(ONE);
1027   } else if (argument_count >= 2) {
1028     minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
1029   } else {
1030     UNREACHABLE();
1031   }
1032   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1033 }
1034
1035
1036 InternalArrayConstructorStub::InternalArrayConstructorStub(
1037     Isolate* isolate) : PlatformCodeStub(isolate) {
1038   InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1039 }
1040
1041
1042 Representation RepresentationFromType(Type* type) {
1043   if (type->Is(Type::UntaggedSigned()) || type->Is(Type::UntaggedUnsigned())) {
1044     return Representation::Integer32();
1045   }
1046
1047   if (type->Is(Type::TaggedSigned())) {
1048     return Representation::Smi();
1049   }
1050
1051   if (type->Is(Type::UntaggedPointer())) {
1052     return Representation::External();
1053   }
1054
1055   DCHECK(!type->Is(Type::Untagged()));
1056   return Representation::Tagged();
1057 }
1058 }  // namespace internal
1059 }  // namespace v8