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/v8.h"
      6 
      7 #include "src/bootstrapper.h"
      8 #include "src/code-stubs.h"
      9 #include "src/cpu-profiler.h"
     10 #include "src/factory.h"
     11 #include "src/gdb-jit.h"
     12 #include "src/ic/handler-compiler.h"
     13 #include "src/ic/ic.h"
     14 #include "src/macro-assembler.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 
     20 CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
     21     : call_descriptor_(stub->GetCallInterfaceDescriptor()),
     22       stack_parameter_count_(no_reg),
     23       hint_stack_parameter_count_(-1),
     24       function_mode_(NOT_JS_FUNCTION_STUB_MODE),
     25       deoptimization_handler_(NULL),
     26       handler_arguments_mode_(DONT_PASS_ARGUMENTS),
     27       miss_handler_(),
     28       has_miss_handler_(false) {
     29   stub->InitializeDescriptor(this);
     30 }
     31 
     32 
     33 CodeStubDescriptor::CodeStubDescriptor(Isolate* isolate, uint32_t stub_key)
     34     : stack_parameter_count_(no_reg),
     35       hint_stack_parameter_count_(-1),
     36       function_mode_(NOT_JS_FUNCTION_STUB_MODE),
     37       deoptimization_handler_(NULL),
     38       handler_arguments_mode_(DONT_PASS_ARGUMENTS),
     39       miss_handler_(),
     40       has_miss_handler_(false) {
     41   CodeStub::InitializeDescriptor(isolate, stub_key, this);
     42 }
     43 
     44 
     45 void CodeStubDescriptor::Initialize(Address deoptimization_handler,
     46                                     int hint_stack_parameter_count,
     47                                     StubFunctionMode function_mode) {
     48   deoptimization_handler_ = deoptimization_handler;
     49   hint_stack_parameter_count_ = hint_stack_parameter_count;
     50   function_mode_ = function_mode;
     51 }
     52 
     53 
     54 void CodeStubDescriptor::Initialize(Register stack_parameter_count,
     55                                     Address deoptimization_handler,
     56                                     int hint_stack_parameter_count,
     57                                     StubFunctionMode function_mode,
     58                                     HandlerArgumentsMode handler_mode) {
     59   Initialize(deoptimization_handler, hint_stack_parameter_count, function_mode);
     60   stack_parameter_count_ = stack_parameter_count;
     61   handler_arguments_mode_ = handler_mode;
     62 }
     63 
     64 
     65 bool CodeStub::FindCodeInCache(Code** code_out) {
     66   UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
     67   int index = stubs->FindEntry(GetKey());
     68   if (index != UnseededNumberDictionary::kNotFound) {
     69     *code_out = Code::cast(stubs->ValueAt(index));
     70     return true;
     71   }
     72   return false;
     73 }
     74 
     75 
     76 void CodeStub::RecordCodeGeneration(Handle<Code> code) {
     77   IC::RegisterWeakMapDependency(code);
     78   OStringStream os;
     79   os << *this;
     80   PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, os.c_str()));
     81   Counters* counters = isolate()->counters();
     82   counters->total_stubs_code_size()->Increment(code->instruction_size());
     83 }
     84 
     85 
     86 Code::Kind CodeStub::GetCodeKind() const {
     87   return Code::STUB;
     88 }
     89 
     90 
     91 Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) {
     92   Handle<Code> ic = GetCode();
     93   ic = isolate()->factory()->CopyCode(ic);
     94   ic->FindAndReplace(pattern);
     95   RecordCodeGeneration(ic);
     96   return ic;
     97 }
     98 
     99 
    100 Handle<Code> PlatformCodeStub::GenerateCode() {
    101   Factory* factory = isolate()->factory();
    102 
    103   // Generate the new code.
    104   MacroAssembler masm(isolate(), NULL, 256);
    105 
    106   // TODO(yangguo) remove this once the code serializer handles code stubs.
    107   if (FLAG_serialize_toplevel) masm.enable_serializer();
    108 
    109   {
    110     // Update the static counter each time a new code stub is generated.
    111     isolate()->counters()->code_stubs()->Increment();
    112 
    113     // Generate the code for the stub.
    114     masm.set_generating_stub(true);
    115     NoCurrentFrameScope scope(&masm);
    116     Generate(&masm);
    117   }
    118 
    119   // Create the code object.
    120   CodeDesc desc;
    121   masm.GetCode(&desc);
    122 
    123   // Copy the generated code into a heap object.
    124   Code::Flags flags = Code::ComputeFlags(
    125       GetCodeKind(),
    126       GetICState(),
    127       GetExtraICState(),
    128       GetStubType());
    129   Handle<Code> new_object = factory->NewCode(
    130       desc, flags, masm.CodeObject(), NeedsImmovableCode());
    131   return new_object;
    132 }
    133 
    134 
    135 Handle<Code> CodeStub::GetCode() {
    136   Heap* heap = isolate()->heap();
    137   Code* code;
    138   if (UseSpecialCache() ? FindCodeInSpecialCache(&code)
    139                         : FindCodeInCache(&code)) {
    140     DCHECK(GetCodeKind() == code->kind());
    141     return Handle<Code>(code);
    142   }
    143 
    144   {
    145     HandleScope scope(isolate());
    146 
    147     Handle<Code> new_object = GenerateCode();
    148     new_object->set_stub_key(GetKey());
    149     FinishCode(new_object);
    150     RecordCodeGeneration(new_object);
    151 
    152 #ifdef ENABLE_DISASSEMBLER
    153     if (FLAG_print_code_stubs) {
    154       CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
    155       OFStream os(trace_scope.file());
    156       OStringStream name;
    157       name << *this;
    158       new_object->Disassemble(name.c_str(), os);
    159       os << "\n";
    160     }
    161 #endif
    162 
    163     if (UseSpecialCache()) {
    164       AddToSpecialCache(new_object);
    165     } else {
    166       // Update the dictionary and the root in Heap.
    167       Handle<UnseededNumberDictionary> dict =
    168           UnseededNumberDictionary::AtNumberPut(
    169               Handle<UnseededNumberDictionary>(heap->code_stubs()),
    170               GetKey(),
    171               new_object);
    172       heap->public_set_code_stubs(*dict);
    173     }
    174     code = *new_object;
    175   }
    176 
    177   Activate(code);
    178   DCHECK(!NeedsImmovableCode() ||
    179          heap->lo_space()->Contains(code) ||
    180          heap->code_space()->FirstPage()->Contains(code->address()));
    181   return Handle<Code>(code, isolate());
    182 }
    183 
    184 
    185 const char* CodeStub::MajorName(CodeStub::Major major_key,
    186                                 bool allow_unknown_keys) {
    187   switch (major_key) {
    188 #define DEF_CASE(name) case name: return #name "Stub";
    189     CODE_STUB_LIST(DEF_CASE)
    190 #undef DEF_CASE
    191     case NoCache:
    192       return "<NoCache>Stub";
    193     case NUMBER_OF_IDS:
    194       UNREACHABLE();
    195       return NULL;
    196   }
    197   return NULL;
    198 }
    199 
    200 
    201 void CodeStub::PrintBaseName(OStream& os) const {  // NOLINT
    202   os << MajorName(MajorKey(), false);
    203 }
    204 
    205 
    206 void CodeStub::PrintName(OStream& os) const {  // NOLINT
    207   PrintBaseName(os);
    208   PrintState(os);
    209 }
    210 
    211 
    212 void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
    213                         DispatchedCall call) {
    214   switch (MajorKeyFromKey(key)) {
    215 #define DEF_CASE(NAME)             \
    216   case NAME: {                     \
    217     NAME##Stub stub(key, isolate); \
    218     CodeStub* pstub = &stub;       \
    219     call(pstub, value_out);        \
    220     break;                         \
    221   }
    222     CODE_STUB_LIST(DEF_CASE)
    223 #undef DEF_CASE
    224     case NUMBER_OF_IDS:
    225       UNREACHABLE();
    226     case NoCache:
    227       *value_out = NULL;
    228       break;
    229   }
    230 }
    231 
    232 
    233 static void InitializeDescriptorDispatchedCall(CodeStub* stub,
    234                                                void** value_out) {
    235   CodeStubDescriptor* descriptor_out =
    236       reinterpret_cast<CodeStubDescriptor*>(value_out);
    237   stub->InitializeDescriptor(descriptor_out);
    238   descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
    239 }
    240 
    241 
    242 void CodeStub::InitializeDescriptor(Isolate* isolate, uint32_t key,
    243                                     CodeStubDescriptor* desc) {
    244   void** value_out = reinterpret_cast<void**>(desc);
    245   Dispatch(isolate, key, value_out, &InitializeDescriptorDispatchedCall);
    246 }
    247 
    248 
    249 void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
    250   Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
    251   // Code stubs with special cache cannot be recreated from stub key.
    252   *code_out = stub->UseSpecialCache() ? Handle<Code>() : stub->GetCode();
    253 }
    254 
    255 
    256 MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
    257   HandleScope scope(isolate);
    258   Handle<Code> code;
    259   void** value_out = reinterpret_cast<void**>(&code);
    260   Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
    261   return scope.CloseAndEscape(code);
    262 }
    263 
    264 
    265 // static
    266 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
    267   // Generate the uninitialized versions of the stub.
    268   for (int op = Token::BIT_OR; op <= Token::MOD; ++op) {
    269     for (int mode = NO_OVERWRITE; mode <= OVERWRITE_RIGHT; ++mode) {
    270       BinaryOpICStub stub(isolate,
    271                           static_cast<Token::Value>(op),
    272                           static_cast<OverwriteMode>(mode));
    273       stub.GetCode();
    274     }
    275   }
    276 
    277   // Generate special versions of the stub.
    278   BinaryOpICState::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
    279 }
    280 
    281 
    282 void BinaryOpICStub::PrintState(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     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 void StringAddStub::PrintBaseName(OStream& os) const {  // NOLINT
    319   os << "StringAddStub";
    320   if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
    321     os << "_CheckBoth";
    322   } else if ((flags() & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
    323     os << "_CheckLeft";
    324   } else if ((flags() & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
    325     os << "_CheckRight";
    326   }
    327   if (pretenure_flag() == TENURED) {
    328     os << "_Tenured";
    329   }
    330 }
    331 
    332 
    333 InlineCacheState CompareICStub::GetICState() const {
    334   CompareICState::State state = Max(left(), right());
    335   switch (state) {
    336     case CompareICState::UNINITIALIZED:
    337       return ::v8::internal::UNINITIALIZED;
    338     case CompareICState::SMI:
    339     case CompareICState::NUMBER:
    340     case CompareICState::INTERNALIZED_STRING:
    341     case CompareICState::STRING:
    342     case CompareICState::UNIQUE_NAME:
    343     case CompareICState::OBJECT:
    344     case CompareICState::KNOWN_OBJECT:
    345       return MONOMORPHIC;
    346     case CompareICState::GENERIC:
    347       return ::v8::internal::GENERIC;
    348   }
    349   UNREACHABLE();
    350   return ::v8::internal::UNINITIALIZED;
    351 }
    352 
    353 
    354 Condition CompareICStub::GetCondition() const {
    355   return CompareIC::ComputeCondition(op());
    356 }
    357 
    358 
    359 void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
    360   DCHECK(*known_map_ != NULL);
    361   Isolate* isolate = new_object->GetIsolate();
    362   Factory* factory = isolate->factory();
    363   return Map::UpdateCodeCache(known_map_,
    364                               strict() ?
    365                                   factory->strict_compare_ic_string() :
    366                                   factory->compare_ic_string(),
    367                               new_object);
    368 }
    369 
    370 
    371 bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
    372   Factory* factory = isolate()->factory();
    373   Code::Flags flags = Code::ComputeFlags(
    374       GetCodeKind(),
    375       UNINITIALIZED);
    376   DCHECK(op() == Token::EQ || op() == Token::EQ_STRICT);
    377   Handle<Object> probe(
    378       known_map_->FindInCodeCache(
    379         strict() ?
    380             *factory->strict_compare_ic_string() :
    381             *factory->compare_ic_string(),
    382         flags),
    383       isolate());
    384   if (probe->IsCode()) {
    385     *code_out = Code::cast(*probe);
    386 #ifdef DEBUG
    387     CompareICStub decode((*code_out)->stub_key(), isolate());
    388     DCHECK(op() == decode.op());
    389     DCHECK(left() == decode.left());
    390     DCHECK(right() == decode.right());
    391     DCHECK(state() == decode.state());
    392 #endif
    393     return true;
    394   }
    395   return false;
    396 }
    397 
    398 
    399 void CompareICStub::Generate(MacroAssembler* masm) {
    400   switch (state()) {
    401     case CompareICState::UNINITIALIZED:
    402       GenerateMiss(masm);
    403       break;
    404     case CompareICState::SMI:
    405       GenerateSmis(masm);
    406       break;
    407     case CompareICState::NUMBER:
    408       GenerateNumbers(masm);
    409       break;
    410     case CompareICState::STRING:
    411       GenerateStrings(masm);
    412       break;
    413     case CompareICState::INTERNALIZED_STRING:
    414       GenerateInternalizedStrings(masm);
    415       break;
    416     case CompareICState::UNIQUE_NAME:
    417       GenerateUniqueNames(masm);
    418       break;
    419     case CompareICState::OBJECT:
    420       GenerateObjects(masm);
    421       break;
    422     case CompareICState::KNOWN_OBJECT:
    423       DCHECK(*known_map_ != NULL);
    424       GenerateKnownObjects(masm);
    425       break;
    426     case CompareICState::GENERIC:
    427       GenerateGeneric(masm);
    428       break;
    429   }
    430 }
    431 
    432 
    433 void CompareNilICStub::UpdateStatus(Handle<Object> object) {
    434   State state = this->state();
    435   DCHECK(!state.Contains(GENERIC));
    436   State old_state = state;
    437   if (object->IsNull()) {
    438     state.Add(NULL_TYPE);
    439   } else if (object->IsUndefined()) {
    440     state.Add(UNDEFINED);
    441   } else if (object->IsUndetectableObject() ||
    442              object->IsOddball() ||
    443              !object->IsHeapObject()) {
    444     state.RemoveAll();
    445     state.Add(GENERIC);
    446   } else if (IsMonomorphic()) {
    447     state.RemoveAll();
    448     state.Add(GENERIC);
    449   } else {
    450     state.Add(MONOMORPHIC_MAP);
    451   }
    452   TraceTransition(old_state, state);
    453   set_sub_minor_key(TypesBits::update(sub_minor_key(), state.ToIntegral()));
    454 }
    455 
    456 
    457 template<class StateType>
    458 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
    459   // Note: Although a no-op transition is semantically OK, it is hinting at a
    460   // bug somewhere in our state transition machinery.
    461   DCHECK(from != to);
    462   if (!FLAG_trace_ic) return;
    463   OFStream os(stdout);
    464   os << "[";
    465   PrintBaseName(os);
    466   os << ": " << from << "=>" << to << "]" << endl;
    467 }
    468 
    469 
    470 void CompareNilICStub::PrintBaseName(OStream& os) const {  // NOLINT
    471   CodeStub::PrintBaseName(os);
    472   os << ((nil_value() == kNullValue) ? "(NullValue)" : "(UndefinedValue)");
    473 }
    474 
    475 
    476 void CompareNilICStub::PrintState(OStream& os) const {  // NOLINT
    477   os << state();
    478 }
    479 
    480 
    481 // TODO(svenpanne) Make this a real infix_ostream_iterator.
    482 class SimpleListPrinter {
    483  public:
    484   explicit SimpleListPrinter(OStream& os) : os_(os), first_(true) {}
    485 
    486   void Add(const char* s) {
    487     if (first_) {
    488       first_ = false;
    489     } else {
    490       os_ << ",";
    491     }
    492     os_ << s;
    493   }
    494 
    495  private:
    496   OStream& os_;
    497   bool first_;
    498 };
    499 
    500 
    501 OStream& operator<<(OStream& os, const CompareNilICStub::State& s) {
    502   os << "(";
    503   SimpleListPrinter p(os);
    504   if (s.IsEmpty()) p.Add("None");
    505   if (s.Contains(CompareNilICStub::UNDEFINED)) p.Add("Undefined");
    506   if (s.Contains(CompareNilICStub::NULL_TYPE)) p.Add("Null");
    507   if (s.Contains(CompareNilICStub::MONOMORPHIC_MAP)) p.Add("MonomorphicMap");
    508   if (s.Contains(CompareNilICStub::GENERIC)) p.Add("Generic");
    509   return os << ")";
    510 }
    511 
    512 
    513 Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
    514   State state = this->state();
    515   if (state.Contains(CompareNilICStub::GENERIC)) return Type::Any(zone);
    516 
    517   Type* result = Type::None(zone);
    518   if (state.Contains(CompareNilICStub::UNDEFINED)) {
    519     result = Type::Union(result, Type::Undefined(zone), zone);
    520   }
    521   if (state.Contains(CompareNilICStub::NULL_TYPE)) {
    522     result = Type::Union(result, Type::Null(zone), zone);
    523   }
    524   if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
    525     Type* type =
    526         map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
    527     result = Type::Union(result, type, zone);
    528   }
    529 
    530   return result;
    531 }
    532 
    533 
    534 Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
    535   Type* output_type = GetType(zone, map);
    536   Type* nil_type =
    537       nil_value() == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
    538   return Type::Union(output_type, nil_type, zone);
    539 }
    540 
    541 
    542 void CallIC_ArrayStub::PrintState(OStream& os) const {  // NOLINT
    543   os << state() << " (Array)";
    544 }
    545 
    546 
    547 void CallICStub::PrintState(OStream& os) const {  // NOLINT
    548   os << state();
    549 }
    550 
    551 
    552 void InstanceofStub::PrintName(OStream& os) const {  // NOLINT
    553   os << "InstanceofStub";
    554   if (HasArgsInRegisters()) os << "_REGS";
    555   if (HasCallSiteInlineCheck()) os << "_INLINE";
    556   if (ReturnTrueFalseObject()) os << "_TRUEFALSE";
    557 }
    558 
    559 
    560 void JSEntryStub::FinishCode(Handle<Code> code) {
    561   Handle<FixedArray> handler_table =
    562       code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
    563   handler_table->set(0, Smi::FromInt(handler_offset_));
    564   code->set_handler_table(*handler_table);
    565 }
    566 
    567 
    568 void LoadFastElementStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    569   descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
    570 }
    571 
    572 
    573 void LoadDictionaryElementStub::InitializeDescriptor(
    574     CodeStubDescriptor* descriptor) {
    575   descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
    576 }
    577 
    578 
    579 void KeyedLoadGenericStub::InitializeDescriptor(
    580     CodeStubDescriptor* descriptor) {
    581   descriptor->Initialize(
    582       Runtime::FunctionForId(Runtime::kKeyedGetProperty)->entry);
    583 }
    584 
    585 
    586 void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    587   if (kind() == Code::STORE_IC) {
    588     descriptor->Initialize(FUNCTION_ADDR(StoreIC_MissFromStubFailure));
    589   } else if (kind() == Code::KEYED_LOAD_IC) {
    590     descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
    591   }
    592 }
    593 
    594 
    595 CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() {
    596   if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
    597     return LoadDescriptor(isolate());
    598   } else {
    599     DCHECK_EQ(Code::STORE_IC, kind());
    600     return StoreDescriptor(isolate());
    601   }
    602 }
    603 
    604 
    605 void StoreFastElementStub::InitializeDescriptor(
    606     CodeStubDescriptor* descriptor) {
    607   descriptor->Initialize(FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
    608 }
    609 
    610 
    611 void ElementsTransitionAndStoreStub::InitializeDescriptor(
    612     CodeStubDescriptor* descriptor) {
    613   descriptor->Initialize(FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss));
    614 }
    615 
    616 
    617 static void InitializeVectorLoadStub(Isolate* isolate,
    618                                      CodeStubDescriptor* descriptor,
    619                                      Address deoptimization_handler) {
    620   DCHECK(FLAG_vector_ics);
    621   descriptor->Initialize(deoptimization_handler);
    622 }
    623 
    624 
    625 void VectorLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    626   InitializeVectorLoadStub(isolate(), descriptor,
    627                            FUNCTION_ADDR(VectorLoadIC_MissFromStubFailure));
    628 }
    629 
    630 
    631 void VectorKeyedLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    632   InitializeVectorLoadStub(
    633       isolate(), descriptor,
    634       FUNCTION_ADDR(VectorKeyedLoadIC_MissFromStubFailure));
    635 }
    636 
    637 
    638 void MegamorphicLoadStub::InitializeDescriptor(CodeStubDescriptor* d) {}
    639 
    640 
    641 void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    642   descriptor->Initialize(
    643       Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry);
    644 }
    645 
    646 
    647 void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
    648 
    649 
    650 void ToNumberStub::InitializeDescriptor(CodeStubDescriptor* d) {}
    651 
    652 
    653 void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    654   NumberToStringDescriptor call_descriptor(isolate());
    655   descriptor->Initialize(
    656       Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry);
    657 }
    658 
    659 
    660 void FastCloneShallowArrayStub::InitializeDescriptor(
    661     CodeStubDescriptor* descriptor) {
    662   FastCloneShallowArrayDescriptor call_descriptor(isolate());
    663   descriptor->Initialize(
    664       Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry);
    665 }
    666 
    667 
    668 void FastCloneShallowObjectStub::InitializeDescriptor(
    669     CodeStubDescriptor* descriptor) {
    670   FastCloneShallowObjectDescriptor call_descriptor(isolate());
    671   descriptor->Initialize(
    672       Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
    673 }
    674 
    675 
    676 void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
    677 
    678 
    679 void RegExpConstructResultStub::InitializeDescriptor(
    680     CodeStubDescriptor* descriptor) {
    681   descriptor->Initialize(
    682       Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry);
    683 }
    684 
    685 
    686 void TransitionElementsKindStub::InitializeDescriptor(
    687     CodeStubDescriptor* descriptor) {
    688   descriptor->Initialize(
    689       Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry);
    690 }
    691 
    692 
    693 void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    694   descriptor->Initialize(FUNCTION_ADDR(CompareNilIC_Miss));
    695   descriptor->SetMissHandler(
    696       ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate()));
    697 }
    698 
    699 
    700 void ToBooleanStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    701   descriptor->Initialize(FUNCTION_ADDR(ToBooleanIC_Miss));
    702   descriptor->SetMissHandler(
    703       ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate()));
    704 }
    705 
    706 
    707 void BinaryOpICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    708   descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_Miss));
    709   descriptor->SetMissHandler(
    710       ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate()));
    711 }
    712 
    713 
    714 void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
    715     CodeStubDescriptor* descriptor) {
    716   descriptor->Initialize(FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite));
    717 }
    718 
    719 
    720 void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
    721   descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAdd)->entry);
    722 }
    723 
    724 
    725 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
    726   CreateAllocationSiteStub stub(isolate);
    727   stub.GetCode();
    728 }
    729 
    730 
    731 void StoreElementStub::Generate(MacroAssembler* masm) {
    732   switch (elements_kind()) {
    733     case FAST_ELEMENTS:
    734     case FAST_HOLEY_ELEMENTS:
    735     case FAST_SMI_ELEMENTS:
    736     case FAST_HOLEY_SMI_ELEMENTS:
    737     case FAST_DOUBLE_ELEMENTS:
    738     case FAST_HOLEY_DOUBLE_ELEMENTS:
    739 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
    740     case EXTERNAL_##TYPE##_ELEMENTS:                    \
    741     case TYPE##_ELEMENTS:
    742 
    743     TYPED_ARRAYS(TYPED_ARRAY_CASE)
    744 #undef TYPED_ARRAY_CASE
    745       UNREACHABLE();
    746       break;
    747     case DICTIONARY_ELEMENTS:
    748       ElementHandlerCompiler::GenerateStoreSlow(masm);
    749       break;
    750     case SLOPPY_ARGUMENTS_ELEMENTS:
    751       UNREACHABLE();
    752       break;
    753   }
    754 }
    755 
    756 
    757 void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
    758   switch (type()) {
    759     case READ_ELEMENT:
    760       GenerateReadElement(masm);
    761       break;
    762     case NEW_SLOPPY_FAST:
    763       GenerateNewSloppyFast(masm);
    764       break;
    765     case NEW_SLOPPY_SLOW:
    766       GenerateNewSloppySlow(masm);
    767       break;
    768     case NEW_STRICT:
    769       GenerateNewStrict(masm);
    770       break;
    771   }
    772 }
    773 
    774 
    775 void ArgumentsAccessStub::PrintName(OStream& os) const {  // NOLINT
    776   os << "ArgumentsAccessStub_";
    777   switch (type()) {
    778     case READ_ELEMENT:
    779       os << "ReadElement";
    780       break;
    781     case NEW_SLOPPY_FAST:
    782       os << "NewSloppyFast";
    783       break;
    784     case NEW_SLOPPY_SLOW:
    785       os << "NewSloppySlow";
    786       break;
    787     case NEW_STRICT:
    788       os << "NewStrict";
    789       break;
    790   }
    791   return;
    792 }
    793 
    794 
    795 void CallFunctionStub::PrintName(OStream& os) const {  // NOLINT
    796   os << "CallFunctionStub_Args" << argc();
    797 }
    798 
    799 
    800 void CallConstructStub::PrintName(OStream& os) const {  // NOLINT
    801   os << "CallConstructStub";
    802   if (RecordCallTarget()) os << "_Recording";
    803 }
    804 
    805 
    806 void ArrayConstructorStub::PrintName(OStream& os) const {  // NOLINT
    807   os << "ArrayConstructorStub";
    808   switch (argument_count()) {
    809     case ANY:
    810       os << "_Any";
    811       break;
    812     case NONE:
    813       os << "_None";
    814       break;
    815     case ONE:
    816       os << "_One";
    817       break;
    818     case MORE_THAN_ONE:
    819       os << "_More_Than_One";
    820       break;
    821   }
    822   return;
    823 }
    824 
    825 
    826 OStream& ArrayConstructorStubBase::BasePrintName(OStream& os,  // NOLINT
    827                                                  const char* name) const {
    828   os << name << "_" << ElementsKindToString(elements_kind());
    829   if (override_mode() == DISABLE_ALLOCATION_SITES) {
    830     os << "_DISABLE_ALLOCATION_SITES";
    831   }
    832   return os;
    833 }
    834 
    835 
    836 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
    837   Types new_types = types();
    838   Types old_types = new_types;
    839   bool to_boolean_value = new_types.UpdateStatus(object);
    840   TraceTransition(old_types, new_types);
    841   set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToByte()));
    842   return to_boolean_value;
    843 }
    844 
    845 
    846 void ToBooleanStub::PrintState(OStream& os) const {  // NOLINT
    847   os << types();
    848 }
    849 
    850 
    851 OStream& operator<<(OStream& os, const ToBooleanStub::Types& s) {
    852   os << "(";
    853   SimpleListPrinter p(os);
    854   if (s.IsEmpty()) p.Add("None");
    855   if (s.Contains(ToBooleanStub::UNDEFINED)) p.Add("Undefined");
    856   if (s.Contains(ToBooleanStub::BOOLEAN)) p.Add("Bool");
    857   if (s.Contains(ToBooleanStub::NULL_TYPE)) p.Add("Null");
    858   if (s.Contains(ToBooleanStub::SMI)) p.Add("Smi");
    859   if (s.Contains(ToBooleanStub::SPEC_OBJECT)) p.Add("SpecObject");
    860   if (s.Contains(ToBooleanStub::STRING)) p.Add("String");
    861   if (s.Contains(ToBooleanStub::SYMBOL)) p.Add("Symbol");
    862   if (s.Contains(ToBooleanStub::HEAP_NUMBER)) p.Add("HeapNumber");
    863   return os << ")";
    864 }
    865 
    866 
    867 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
    868   if (object->IsUndefined()) {
    869     Add(UNDEFINED);
    870     return false;
    871   } else if (object->IsBoolean()) {
    872     Add(BOOLEAN);
    873     return object->IsTrue();
    874   } else if (object->IsNull()) {
    875     Add(NULL_TYPE);
    876     return false;
    877   } else if (object->IsSmi()) {
    878     Add(SMI);
    879     return Smi::cast(*object)->value() != 0;
    880   } else if (object->IsSpecObject()) {
    881     Add(SPEC_OBJECT);
    882     return !object->IsUndetectableObject();
    883   } else if (object->IsString()) {
    884     Add(STRING);
    885     return !object->IsUndetectableObject() &&
    886         String::cast(*object)->length() != 0;
    887   } else if (object->IsSymbol()) {
    888     Add(SYMBOL);
    889     return true;
    890   } else if (object->IsHeapNumber()) {
    891     DCHECK(!object->IsUndetectableObject());
    892     Add(HEAP_NUMBER);
    893     double value = HeapNumber::cast(*object)->value();
    894     return value != 0 && !std::isnan(value);
    895   } else {
    896     // We should never see an internal object at runtime here!
    897     UNREACHABLE();
    898     return true;
    899   }
    900 }
    901 
    902 
    903 bool ToBooleanStub::Types::NeedsMap() const {
    904   return Contains(ToBooleanStub::SPEC_OBJECT)
    905       || Contains(ToBooleanStub::STRING)
    906       || Contains(ToBooleanStub::SYMBOL)
    907       || Contains(ToBooleanStub::HEAP_NUMBER);
    908 }
    909 
    910 
    911 bool ToBooleanStub::Types::CanBeUndetectable() const {
    912   return Contains(ToBooleanStub::SPEC_OBJECT)
    913       || Contains(ToBooleanStub::STRING);
    914 }
    915 
    916 
    917 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
    918   StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
    919   StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
    920   stub1.GetCode();
    921   stub2.GetCode();
    922 }
    923 
    924 
    925 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
    926                                                intptr_t stack_pointer,
    927                                                Isolate* isolate) {
    928   FunctionEntryHook entry_hook = isolate->function_entry_hook();
    929   DCHECK(entry_hook != NULL);
    930   entry_hook(function, stack_pointer);
    931 }
    932 
    933 
    934 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
    935     : PlatformCodeStub(isolate) {
    936   minor_key_ = ArgumentCountBits::encode(ANY);
    937   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
    938 }
    939 
    940 
    941 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
    942                                            int argument_count)
    943     : PlatformCodeStub(isolate) {
    944   if (argument_count == 0) {
    945     minor_key_ = ArgumentCountBits::encode(NONE);
    946   } else if (argument_count == 1) {
    947     minor_key_ = ArgumentCountBits::encode(ONE);
    948   } else if (argument_count >= 2) {
    949     minor_key_ = ArgumentCountBits::encode(MORE_THAN_ONE);
    950   } else {
    951     UNREACHABLE();
    952   }
    953   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
    954 }
    955 
    956 
    957 InternalArrayConstructorStub::InternalArrayConstructorStub(
    958     Isolate* isolate) : PlatformCodeStub(isolate) {
    959   InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
    960 }
    961 
    962 
    963 } }  // namespace v8::internal
    964