Home | History | Annotate | Download | only in src
      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 
     23 RUNTIME_FUNCTION(UnexpectedStubMiss) {
     24   FATAL("Unexpected deopt of a stub");
     25   return Smi::FromInt(0);
     26 }
     27 
     28 
     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 
     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 
     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 
     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 
     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 
     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 
     94 Code::Kind CodeStub::GetCodeKind() const {
     95   return Code::STUB;
     96 }
     97 
     98 
     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 
    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 
    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 
    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 
    206 void CodeStub::PrintBaseName(std::ostream& os) const {  // NOLINT
    207   os << MajorName(MajorKey());
    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     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 
    340 void StringAddStub::PrintBaseName(std::ostream& os) const {  // NOLINT
    341   os << "StringAddStub_" << flags() << "_" << pretenure_flag();
    342 }
    343 
    344 
    345 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 
    367 Condition CompareICStub::GetCondition() const {
    368   return CompareIC::ComputeCondition(op());
    369 }
    370 
    371 
    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 
    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 
    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 
    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 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 
    483 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>
    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 
    507 void CompareNilICStub::PrintBaseName(std::ostream& os) const {  // NOLINT
    508   CodeStub::PrintBaseName(os);
    509   os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
    510 }
    511 
    512 
    513 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:
    521   explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {}
    522 
    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 
    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 
    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 
    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 
    579 void CallICStub::PrintState(std::ostream& os) const {  // NOLINT
    580   os << state();
    581 }
    582 
    583 
    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 
    592 void LoadDictionaryElementStub::InitializeDescriptor(
    593     CodeStubDescriptor* descriptor) {
    594   descriptor->Initialize(
    595       FUNCTION_ADDR(Runtime_KeyedLoadIC_MissFromStubFailure));
    596 }
    597 
    598 
    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 
    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 
    621 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 
    631 void StoreFastElementStub::InitializeDescriptor(
    632     CodeStubDescriptor* descriptor) {
    633   descriptor->Initialize(
    634       FUNCTION_ADDR(Runtime_KeyedStoreIC_MissFromStubFailure));
    635 }
    636 
    637 
    638 void ElementsTransitionAndStoreStub::InitializeDescriptor(
    639     CodeStubDescriptor* descriptor) {
    640   descriptor->Initialize(
    641       FUNCTION_ADDR(Runtime_ElementsTransitionAndStoreIC_Miss));
    642 }
    643 
    644 
    645 void ToObjectStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    646   descriptor->Initialize(Runtime::FunctionForId(Runtime::kToObject)->entry);
    647 }
    648 
    649 
    650 CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor()
    651     const {
    652   return VectorStoreTransitionDescriptor(isolate());
    653 }
    654 
    655 
    656 CallInterfaceDescriptor
    657 ElementsTransitionAndStoreStub::GetCallInterfaceDescriptor() const {
    658   return VectorStoreTransitionDescriptor(isolate());
    659 }
    660 
    661 
    662 void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    663   descriptor->Initialize(Runtime::FunctionForId(Runtime::kNewClosure)->entry);
    664 }
    665 
    666 
    667 void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
    668 
    669 
    670 void TypeofStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {}
    671 
    672 
    673 void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    674   NumberToStringDescriptor call_descriptor(isolate());
    675   descriptor->Initialize(
    676       Runtime::FunctionForId(Runtime::kNumberToString)->entry);
    677 }
    678 
    679 
    680 void FastCloneRegExpStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    681   FastCloneRegExpDescriptor call_descriptor(isolate());
    682   descriptor->Initialize(
    683       Runtime::FunctionForId(Runtime::kCreateRegExpLiteral)->entry);
    684 }
    685 
    686 
    687 void FastCloneShallowArrayStub::InitializeDescriptor(
    688     CodeStubDescriptor* descriptor) {
    689   FastCloneShallowArrayDescriptor call_descriptor(isolate());
    690   descriptor->Initialize(
    691       Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
    692 }
    693 
    694 
    695 void FastCloneShallowObjectStub::InitializeDescriptor(
    696     CodeStubDescriptor* descriptor) {
    697   FastCloneShallowObjectDescriptor call_descriptor(isolate());
    698   descriptor->Initialize(
    699       Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
    700 }
    701 
    702 
    703 void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
    704 
    705 
    706 void CreateWeakCellStub::InitializeDescriptor(CodeStubDescriptor* d) {}
    707 
    708 
    709 void RegExpConstructResultStub::InitializeDescriptor(
    710     CodeStubDescriptor* descriptor) {
    711   descriptor->Initialize(
    712       Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry);
    713 }
    714 
    715 
    716 void TransitionElementsKindStub::InitializeDescriptor(
    717     CodeStubDescriptor* descriptor) {
    718   descriptor->Initialize(
    719       Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
    720 }
    721 
    722 
    723 void AllocateHeapNumberStub::InitializeDescriptor(
    724     CodeStubDescriptor* descriptor) {
    725   descriptor->Initialize(
    726       Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry);
    727 }
    728 
    729 
    730 void AllocateMutableHeapNumberStub::InitializeDescriptor(
    731     CodeStubDescriptor* descriptor) {
    732   descriptor->Initialize();
    733 }
    734 
    735 
    736 void AllocateInNewSpaceStub::InitializeDescriptor(
    737     CodeStubDescriptor* descriptor) {
    738   descriptor->Initialize();
    739 }
    740 
    741 
    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 
    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 
    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 
    763 void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
    764     CodeStubDescriptor* descriptor) {
    765   descriptor->Initialize(
    766       FUNCTION_ADDR(Runtime_BinaryOpIC_MissWithAllocationSite));
    767 }
    768 
    769 
    770 void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    771   descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAdd)->entry);
    772 }
    773 
    774 
    775 void GrowArrayElementsStub::InitializeDescriptor(
    776     CodeStubDescriptor* descriptor) {
    777   descriptor->Initialize(
    778       Runtime::FunctionForId(Runtime::kGrowArrayElements)->entry);
    779 }
    780 
    781 
    782 void TypeofStub::GenerateAheadOfTime(Isolate* isolate) {
    783   TypeofStub stub(isolate);
    784   stub.GetCode();
    785 }
    786 
    787 
    788 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
    789   CreateAllocationSiteStub stub(isolate);
    790   stub.GetCode();
    791 }
    792 
    793 
    794 void CreateWeakCellStub::GenerateAheadOfTime(Isolate* isolate) {
    795   CreateWeakCellStub stub(isolate);
    796   stub.GetCode();
    797 }
    798 
    799 
    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
    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 
    841 void RestParamAccessStub::Generate(MacroAssembler* masm) { GenerateNew(masm); }
    842 
    843 
    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 
    862 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 
    882 void RestParamAccessStub::PrintName(std::ostream& os) const {  // NOLINT
    883   os << "RestParamAccessStub_";
    884 }
    885 
    886 
    887 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 
    907 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 
    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 
    928 void ToBooleanStub::PrintState(std::ostream& os) const {  // NOLINT
    929   os << types();
    930 }
    931 
    932 
    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 
    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 
    989 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 
    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 
   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 
   1014 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
   1015     : PlatformCodeStub(isolate) {
   1016   minor_key_ = ArgumentCountBits::encode(ANY);
   1017   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
   1018 }
   1019 
   1020 
   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 
   1037 InternalArrayConstructorStub::InternalArrayConstructorStub(
   1038     Isolate* isolate) : PlatformCodeStub(isolate) {
   1039   InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
   1040 }
   1041 
   1042 
   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