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