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