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