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