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/stub-cache.h"
     11 #include "src/factory.h"
     12 #include "src/gdb-jit.h"
     13 #include "src/macro-assembler.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 
     18 
     19 CodeStubInterfaceDescriptor::CodeStubInterfaceDescriptor()
     20     : register_param_count_(-1),
     21       stack_parameter_count_(no_reg),
     22       hint_stack_parameter_count_(-1),
     23       function_mode_(NOT_JS_FUNCTION_STUB_MODE),
     24       register_params_(NULL),
     25       register_param_representations_(NULL),
     26       deoptimization_handler_(NULL),
     27       handler_arguments_mode_(DONT_PASS_ARGUMENTS),
     28       miss_handler_(),
     29       has_miss_handler_(false) { }
     30 
     31 
     32 bool CodeStub::FindCodeInCache(Code** code_out) {
     33   UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs();
     34   int index = stubs->FindEntry(GetKey());
     35   if (index != UnseededNumberDictionary::kNotFound) {
     36     *code_out = Code::cast(stubs->ValueAt(index));
     37     return true;
     38   }
     39   return false;
     40 }
     41 
     42 
     43 SmartArrayPointer<const char> CodeStub::GetName() {
     44   char buffer[100];
     45   NoAllocationStringAllocator allocator(buffer,
     46                                         static_cast<unsigned>(sizeof(buffer)));
     47   StringStream stream(&allocator);
     48   PrintName(&stream);
     49   return stream.ToCString();
     50 }
     51 
     52 
     53 void CodeStub::RecordCodeGeneration(Handle<Code> code) {
     54   IC::RegisterWeakMapDependency(code);
     55   SmartArrayPointer<const char> name = GetName();
     56   PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, name.get()));
     57   GDBJIT(AddCode(GDBJITInterface::STUB, name.get(), *code));
     58   Counters* counters = isolate()->counters();
     59   counters->total_stubs_code_size()->Increment(code->instruction_size());
     60 }
     61 
     62 
     63 Code::Kind CodeStub::GetCodeKind() const {
     64   return Code::STUB;
     65 }
     66 
     67 
     68 Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) {
     69   Handle<Code> ic = GetCode();
     70   ic = isolate()->factory()->CopyCode(ic);
     71   ic->FindAndReplace(pattern);
     72   RecordCodeGeneration(ic);
     73   return ic;
     74 }
     75 
     76 
     77 Handle<Code> PlatformCodeStub::GenerateCode() {
     78   Factory* factory = isolate()->factory();
     79 
     80   // Generate the new code.
     81   MacroAssembler masm(isolate(), NULL, 256);
     82 
     83   {
     84     // Update the static counter each time a new code stub is generated.
     85     isolate()->counters()->code_stubs()->Increment();
     86 
     87     // Generate the code for the stub.
     88     masm.set_generating_stub(true);
     89     NoCurrentFrameScope scope(&masm);
     90     Generate(&masm);
     91   }
     92 
     93   // Create the code object.
     94   CodeDesc desc;
     95   masm.GetCode(&desc);
     96 
     97   // Copy the generated code into a heap object.
     98   Code::Flags flags = Code::ComputeFlags(
     99       GetCodeKind(),
    100       GetICState(),
    101       GetExtraICState(),
    102       GetStubType());
    103   Handle<Code> new_object = factory->NewCode(
    104       desc, flags, masm.CodeObject(), NeedsImmovableCode());
    105   return new_object;
    106 }
    107 
    108 
    109 Handle<Code> CodeStub::GetCode() {
    110   Heap* heap = isolate()->heap();
    111   Code* code;
    112   if (UseSpecialCache()
    113       ? FindCodeInSpecialCache(&code)
    114       : FindCodeInCache(&code)) {
    115     ASSERT(GetCodeKind() == code->kind());
    116     return Handle<Code>(code);
    117   }
    118 
    119   {
    120     HandleScope scope(isolate());
    121 
    122     Handle<Code> new_object = GenerateCode();
    123     new_object->set_major_key(MajorKey());
    124     FinishCode(new_object);
    125     RecordCodeGeneration(new_object);
    126 
    127 #ifdef ENABLE_DISASSEMBLER
    128     if (FLAG_print_code_stubs) {
    129       CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
    130       new_object->Disassemble(GetName().get(), trace_scope.file());
    131       PrintF(trace_scope.file(), "\n");
    132     }
    133 #endif
    134 
    135     if (UseSpecialCache()) {
    136       AddToSpecialCache(new_object);
    137     } else {
    138       // Update the dictionary and the root in Heap.
    139       Handle<UnseededNumberDictionary> dict =
    140           UnseededNumberDictionary::AtNumberPut(
    141               Handle<UnseededNumberDictionary>(heap->code_stubs()),
    142               GetKey(),
    143               new_object);
    144       heap->public_set_code_stubs(*dict);
    145     }
    146     code = *new_object;
    147   }
    148 
    149   Activate(code);
    150   ASSERT(!NeedsImmovableCode() ||
    151          heap->lo_space()->Contains(code) ||
    152          heap->code_space()->FirstPage()->Contains(code->address()));
    153   return Handle<Code>(code, isolate());
    154 }
    155 
    156 
    157 const char* CodeStub::MajorName(CodeStub::Major major_key,
    158                                 bool allow_unknown_keys) {
    159   switch (major_key) {
    160 #define DEF_CASE(name) case name: return #name "Stub";
    161     CODE_STUB_LIST(DEF_CASE)
    162 #undef DEF_CASE
    163     case UninitializedMajorKey: return "<UninitializedMajorKey>Stub";
    164     default:
    165       if (!allow_unknown_keys) {
    166         UNREACHABLE();
    167       }
    168       return NULL;
    169   }
    170 }
    171 
    172 
    173 void CodeStub::PrintBaseName(StringStream* stream) {
    174   stream->Add("%s", MajorName(MajorKey(), false));
    175 }
    176 
    177 
    178 void CodeStub::PrintName(StringStream* stream) {
    179   PrintBaseName(stream);
    180   PrintState(stream);
    181 }
    182 
    183 
    184 // static
    185 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate) {
    186   // Generate the uninitialized versions of the stub.
    187   for (int op = Token::BIT_OR; op <= Token::MOD; ++op) {
    188     for (int mode = NO_OVERWRITE; mode <= OVERWRITE_RIGHT; ++mode) {
    189       BinaryOpICStub stub(isolate,
    190                           static_cast<Token::Value>(op),
    191                           static_cast<OverwriteMode>(mode));
    192       stub.GetCode();
    193     }
    194   }
    195 
    196   // Generate special versions of the stub.
    197   BinaryOpIC::State::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
    198 }
    199 
    200 
    201 void BinaryOpICStub::PrintState(StringStream* stream) {
    202   state_.Print(stream);
    203 }
    204 
    205 
    206 // static
    207 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
    208                                          const BinaryOpIC::State& state) {
    209   BinaryOpICStub stub(isolate, state);
    210   stub.GetCode();
    211 }
    212 
    213 
    214 // static
    215 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
    216   // Generate special versions of the stub.
    217   BinaryOpIC::State::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
    218 }
    219 
    220 
    221 void BinaryOpICWithAllocationSiteStub::PrintState(StringStream* stream) {
    222   state_.Print(stream);
    223 }
    224 
    225 
    226 // static
    227 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
    228     Isolate* isolate, const BinaryOpIC::State& state) {
    229   if (state.CouldCreateAllocationMementos()) {
    230     BinaryOpICWithAllocationSiteStub stub(isolate, state);
    231     stub.GetCode();
    232   }
    233 }
    234 
    235 
    236 void StringAddStub::PrintBaseName(StringStream* stream) {
    237   stream->Add("StringAddStub");
    238   if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
    239     stream->Add("_CheckBoth");
    240   } else if ((flags() & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
    241     stream->Add("_CheckLeft");
    242   } else if ((flags() & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
    243     stream->Add("_CheckRight");
    244   }
    245   if (pretenure_flag() == TENURED) {
    246     stream->Add("_Tenured");
    247   }
    248 }
    249 
    250 
    251 InlineCacheState ICCompareStub::GetICState() {
    252   CompareIC::State state = Max(left_, right_);
    253   switch (state) {
    254     case CompareIC::UNINITIALIZED:
    255       return ::v8::internal::UNINITIALIZED;
    256     case CompareIC::SMI:
    257     case CompareIC::NUMBER:
    258     case CompareIC::INTERNALIZED_STRING:
    259     case CompareIC::STRING:
    260     case CompareIC::UNIQUE_NAME:
    261     case CompareIC::OBJECT:
    262     case CompareIC::KNOWN_OBJECT:
    263       return MONOMORPHIC;
    264     case CompareIC::GENERIC:
    265       return ::v8::internal::GENERIC;
    266   }
    267   UNREACHABLE();
    268   return ::v8::internal::UNINITIALIZED;
    269 }
    270 
    271 
    272 void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) {
    273   ASSERT(*known_map_ != NULL);
    274   Isolate* isolate = new_object->GetIsolate();
    275   Factory* factory = isolate->factory();
    276   return Map::UpdateCodeCache(known_map_,
    277                               strict() ?
    278                                   factory->strict_compare_ic_string() :
    279                                   factory->compare_ic_string(),
    280                               new_object);
    281 }
    282 
    283 
    284 bool ICCompareStub::FindCodeInSpecialCache(Code** code_out) {
    285   Factory* factory = isolate()->factory();
    286   Code::Flags flags = Code::ComputeFlags(
    287       GetCodeKind(),
    288       UNINITIALIZED);
    289   ASSERT(op_ == Token::EQ || op_ == Token::EQ_STRICT);
    290   Handle<Object> probe(
    291       known_map_->FindInCodeCache(
    292         strict() ?
    293             *factory->strict_compare_ic_string() :
    294             *factory->compare_ic_string(),
    295         flags),
    296       isolate());
    297   if (probe->IsCode()) {
    298     *code_out = Code::cast(*probe);
    299 #ifdef DEBUG
    300     Token::Value cached_op;
    301     ICCompareStub::DecodeMinorKey((*code_out)->stub_info(), NULL, NULL, NULL,
    302                                   &cached_op);
    303     ASSERT(op_ == cached_op);
    304 #endif
    305     return true;
    306   }
    307   return false;
    308 }
    309 
    310 
    311 int ICCompareStub::MinorKey() {
    312   return OpField::encode(op_ - Token::EQ) |
    313          LeftStateField::encode(left_) |
    314          RightStateField::encode(right_) |
    315          HandlerStateField::encode(state_);
    316 }
    317 
    318 
    319 void ICCompareStub::DecodeMinorKey(int minor_key,
    320                                    CompareIC::State* left_state,
    321                                    CompareIC::State* right_state,
    322                                    CompareIC::State* handler_state,
    323                                    Token::Value* op) {
    324   if (left_state) {
    325     *left_state =
    326         static_cast<CompareIC::State>(LeftStateField::decode(minor_key));
    327   }
    328   if (right_state) {
    329     *right_state =
    330         static_cast<CompareIC::State>(RightStateField::decode(minor_key));
    331   }
    332   if (handler_state) {
    333     *handler_state =
    334         static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
    335   }
    336   if (op) {
    337     *op = static_cast<Token::Value>(OpField::decode(minor_key) + Token::EQ);
    338   }
    339 }
    340 
    341 
    342 void ICCompareStub::Generate(MacroAssembler* masm) {
    343   switch (state_) {
    344     case CompareIC::UNINITIALIZED:
    345       GenerateMiss(masm);
    346       break;
    347     case CompareIC::SMI:
    348       GenerateSmis(masm);
    349       break;
    350     case CompareIC::NUMBER:
    351       GenerateNumbers(masm);
    352       break;
    353     case CompareIC::STRING:
    354       GenerateStrings(masm);
    355       break;
    356     case CompareIC::INTERNALIZED_STRING:
    357       GenerateInternalizedStrings(masm);
    358       break;
    359     case CompareIC::UNIQUE_NAME:
    360       GenerateUniqueNames(masm);
    361       break;
    362     case CompareIC::OBJECT:
    363       GenerateObjects(masm);
    364       break;
    365     case CompareIC::KNOWN_OBJECT:
    366       ASSERT(*known_map_ != NULL);
    367       GenerateKnownObjects(masm);
    368       break;
    369     case CompareIC::GENERIC:
    370       GenerateGeneric(masm);
    371       break;
    372   }
    373 }
    374 
    375 
    376 void CompareNilICStub::UpdateStatus(Handle<Object> object) {
    377   ASSERT(!state_.Contains(GENERIC));
    378   State old_state(state_);
    379   if (object->IsNull()) {
    380     state_.Add(NULL_TYPE);
    381   } else if (object->IsUndefined()) {
    382     state_.Add(UNDEFINED);
    383   } else if (object->IsUndetectableObject() ||
    384              object->IsOddball() ||
    385              !object->IsHeapObject()) {
    386     state_.RemoveAll();
    387     state_.Add(GENERIC);
    388   } else if (IsMonomorphic()) {
    389     state_.RemoveAll();
    390     state_.Add(GENERIC);
    391   } else {
    392     state_.Add(MONOMORPHIC_MAP);
    393   }
    394   TraceTransition(old_state, state_);
    395 }
    396 
    397 
    398 template<class StateType>
    399 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
    400   // Note: Although a no-op transition is semantically OK, it is hinting at a
    401   // bug somewhere in our state transition machinery.
    402   ASSERT(from != to);
    403   if (!FLAG_trace_ic) return;
    404   char buffer[100];
    405   NoAllocationStringAllocator allocator(buffer,
    406                                         static_cast<unsigned>(sizeof(buffer)));
    407   StringStream stream(&allocator);
    408   stream.Add("[");
    409   PrintBaseName(&stream);
    410   stream.Add(": ");
    411   from.Print(&stream);
    412   stream.Add("=>");
    413   to.Print(&stream);
    414   stream.Add("]\n");
    415   stream.OutputToStdOut();
    416 }
    417 
    418 
    419 void CompareNilICStub::PrintBaseName(StringStream* stream) {
    420   CodeStub::PrintBaseName(stream);
    421   stream->Add((nil_value_ == kNullValue) ? "(NullValue)":
    422                                            "(UndefinedValue)");
    423 }
    424 
    425 
    426 void CompareNilICStub::PrintState(StringStream* stream) {
    427   state_.Print(stream);
    428 }
    429 
    430 
    431 void CompareNilICStub::State::Print(StringStream* stream) const {
    432   stream->Add("(");
    433   SimpleListPrinter printer(stream);
    434   if (IsEmpty()) printer.Add("None");
    435   if (Contains(UNDEFINED)) printer.Add("Undefined");
    436   if (Contains(NULL_TYPE)) printer.Add("Null");
    437   if (Contains(MONOMORPHIC_MAP)) printer.Add("MonomorphicMap");
    438   if (Contains(GENERIC)) printer.Add("Generic");
    439   stream->Add(")");
    440 }
    441 
    442 
    443 Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
    444   if (state_.Contains(CompareNilICStub::GENERIC)) {
    445     return Type::Any(zone);
    446   }
    447 
    448   Type* result = Type::None(zone);
    449   if (state_.Contains(CompareNilICStub::UNDEFINED)) {
    450     result = Type::Union(result, Type::Undefined(zone), zone);
    451   }
    452   if (state_.Contains(CompareNilICStub::NULL_TYPE)) {
    453     result = Type::Union(result, Type::Null(zone), zone);
    454   }
    455   if (state_.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
    456     Type* type =
    457         map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
    458     result = Type::Union(result, type, zone);
    459   }
    460 
    461   return result;
    462 }
    463 
    464 
    465 Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
    466   Type* output_type = GetType(zone, map);
    467   Type* nil_type =
    468       nil_value_ == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
    469   return Type::Union(output_type, nil_type, zone);
    470 }
    471 
    472 
    473 void CallIC_ArrayStub::PrintState(StringStream* stream) {
    474   state_.Print(stream);
    475   stream->Add(" (Array)");
    476 }
    477 
    478 
    479 void CallICStub::PrintState(StringStream* stream) {
    480   state_.Print(stream);
    481 }
    482 
    483 
    484 void InstanceofStub::PrintName(StringStream* stream) {
    485   const char* args = "";
    486   if (HasArgsInRegisters()) {
    487     args = "_REGS";
    488   }
    489 
    490   const char* inline_check = "";
    491   if (HasCallSiteInlineCheck()) {
    492     inline_check = "_INLINE";
    493   }
    494 
    495   const char* return_true_false_object = "";
    496   if (ReturnTrueFalseObject()) {
    497     return_true_false_object = "_TRUEFALSE";
    498   }
    499 
    500   stream->Add("InstanceofStub%s%s%s",
    501               args,
    502               inline_check,
    503               return_true_false_object);
    504 }
    505 
    506 
    507 void JSEntryStub::FinishCode(Handle<Code> code) {
    508   Handle<FixedArray> handler_table =
    509       code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
    510   handler_table->set(0, Smi::FromInt(handler_offset_));
    511   code->set_handler_table(*handler_table);
    512 }
    513 
    514 
    515 void KeyedLoadDictionaryElementPlatformStub::Generate(
    516     MacroAssembler* masm) {
    517   KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm);
    518 }
    519 
    520 
    521 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
    522   CreateAllocationSiteStub stub(isolate);
    523   stub.GetCode();
    524 }
    525 
    526 
    527 void KeyedStoreElementStub::Generate(MacroAssembler* masm) {
    528   switch (elements_kind_) {
    529     case FAST_ELEMENTS:
    530     case FAST_HOLEY_ELEMENTS:
    531     case FAST_SMI_ELEMENTS:
    532     case FAST_HOLEY_SMI_ELEMENTS:
    533     case FAST_DOUBLE_ELEMENTS:
    534     case FAST_HOLEY_DOUBLE_ELEMENTS:
    535 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
    536     case EXTERNAL_##TYPE##_ELEMENTS:                    \
    537     case TYPE##_ELEMENTS:
    538 
    539     TYPED_ARRAYS(TYPED_ARRAY_CASE)
    540 #undef TYPED_ARRAY_CASE
    541       UNREACHABLE();
    542       break;
    543     case DICTIONARY_ELEMENTS:
    544       KeyedStoreStubCompiler::GenerateStoreDictionaryElement(masm);
    545       break;
    546     case SLOPPY_ARGUMENTS_ELEMENTS:
    547       UNREACHABLE();
    548       break;
    549   }
    550 }
    551 
    552 
    553 void ArgumentsAccessStub::PrintName(StringStream* stream) {
    554   stream->Add("ArgumentsAccessStub_");
    555   switch (type_) {
    556     case READ_ELEMENT: stream->Add("ReadElement"); break;
    557     case NEW_SLOPPY_FAST: stream->Add("NewSloppyFast"); break;
    558     case NEW_SLOPPY_SLOW: stream->Add("NewSloppySlow"); break;
    559     case NEW_STRICT: stream->Add("NewStrict"); break;
    560   }
    561 }
    562 
    563 
    564 void CallFunctionStub::PrintName(StringStream* stream) {
    565   stream->Add("CallFunctionStub_Args%d", argc_);
    566 }
    567 
    568 
    569 void CallConstructStub::PrintName(StringStream* stream) {
    570   stream->Add("CallConstructStub");
    571   if (RecordCallTarget()) stream->Add("_Recording");
    572 }
    573 
    574 
    575 void ArrayConstructorStub::PrintName(StringStream* stream) {
    576   stream->Add("ArrayConstructorStub");
    577   switch (argument_count_) {
    578     case ANY: stream->Add("_Any"); break;
    579     case NONE: stream->Add("_None"); break;
    580     case ONE: stream->Add("_One"); break;
    581     case MORE_THAN_ONE: stream->Add("_More_Than_One"); break;
    582   }
    583 }
    584 
    585 
    586 void ArrayConstructorStubBase::BasePrintName(const char* name,
    587                                              StringStream* stream) {
    588   stream->Add(name);
    589   stream->Add("_");
    590   stream->Add(ElementsKindToString(elements_kind()));
    591   if (override_mode() == DISABLE_ALLOCATION_SITES) {
    592     stream->Add("_DISABLE_ALLOCATION_SITES");
    593   }
    594 }
    595 
    596 
    597 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
    598   Types old_types(types_);
    599   bool to_boolean_value = types_.UpdateStatus(object);
    600   TraceTransition(old_types, types_);
    601   return to_boolean_value;
    602 }
    603 
    604 
    605 void ToBooleanStub::PrintState(StringStream* stream) {
    606   types_.Print(stream);
    607 }
    608 
    609 
    610 void ToBooleanStub::Types::Print(StringStream* stream) const {
    611   stream->Add("(");
    612   SimpleListPrinter printer(stream);
    613   if (IsEmpty()) printer.Add("None");
    614   if (Contains(UNDEFINED)) printer.Add("Undefined");
    615   if (Contains(BOOLEAN)) printer.Add("Bool");
    616   if (Contains(NULL_TYPE)) printer.Add("Null");
    617   if (Contains(SMI)) printer.Add("Smi");
    618   if (Contains(SPEC_OBJECT)) printer.Add("SpecObject");
    619   if (Contains(STRING)) printer.Add("String");
    620   if (Contains(SYMBOL)) printer.Add("Symbol");
    621   if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber");
    622   stream->Add(")");
    623 }
    624 
    625 
    626 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
    627   if (object->IsUndefined()) {
    628     Add(UNDEFINED);
    629     return false;
    630   } else if (object->IsBoolean()) {
    631     Add(BOOLEAN);
    632     return object->IsTrue();
    633   } else if (object->IsNull()) {
    634     Add(NULL_TYPE);
    635     return false;
    636   } else if (object->IsSmi()) {
    637     Add(SMI);
    638     return Smi::cast(*object)->value() != 0;
    639   } else if (object->IsSpecObject()) {
    640     Add(SPEC_OBJECT);
    641     return !object->IsUndetectableObject();
    642   } else if (object->IsString()) {
    643     Add(STRING);
    644     return !object->IsUndetectableObject() &&
    645         String::cast(*object)->length() != 0;
    646   } else if (object->IsSymbol()) {
    647     Add(SYMBOL);
    648     return true;
    649   } else if (object->IsHeapNumber()) {
    650     ASSERT(!object->IsUndetectableObject());
    651     Add(HEAP_NUMBER);
    652     double value = HeapNumber::cast(*object)->value();
    653     return value != 0 && !std::isnan(value);
    654   } else {
    655     // We should never see an internal object at runtime here!
    656     UNREACHABLE();
    657     return true;
    658   }
    659 }
    660 
    661 
    662 bool ToBooleanStub::Types::NeedsMap() const {
    663   return Contains(ToBooleanStub::SPEC_OBJECT)
    664       || Contains(ToBooleanStub::STRING)
    665       || Contains(ToBooleanStub::SYMBOL)
    666       || Contains(ToBooleanStub::HEAP_NUMBER);
    667 }
    668 
    669 
    670 bool ToBooleanStub::Types::CanBeUndetectable() const {
    671   return Contains(ToBooleanStub::SPEC_OBJECT)
    672       || Contains(ToBooleanStub::STRING);
    673 }
    674 
    675 
    676 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
    677   StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE);
    678   StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE);
    679   stub1.GetCode();
    680   stub2.GetCode();
    681 }
    682 
    683 
    684 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
    685                                                intptr_t stack_pointer,
    686                                                Isolate* isolate) {
    687   FunctionEntryHook entry_hook = isolate->function_entry_hook();
    688   ASSERT(entry_hook != NULL);
    689   entry_hook(function, stack_pointer);
    690 }
    691 
    692 
    693 static void InstallDescriptor(Isolate* isolate, HydrogenCodeStub* stub) {
    694   int major_key = stub->MajorKey();
    695   CodeStubInterfaceDescriptor* descriptor =
    696       isolate->code_stub_interface_descriptor(major_key);
    697   if (!descriptor->initialized()) {
    698     stub->InitializeInterfaceDescriptor(descriptor);
    699   }
    700 }
    701 
    702 
    703 void ArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
    704   ArrayNoArgumentConstructorStub stub1(isolate, GetInitialFastElementsKind());
    705   InstallDescriptor(isolate, &stub1);
    706   ArraySingleArgumentConstructorStub stub2(isolate,
    707                                            GetInitialFastElementsKind());
    708   InstallDescriptor(isolate, &stub2);
    709   ArrayNArgumentsConstructorStub stub3(isolate, GetInitialFastElementsKind());
    710   InstallDescriptor(isolate, &stub3);
    711 }
    712 
    713 
    714 void NumberToStringStub::InstallDescriptors(Isolate* isolate) {
    715   NumberToStringStub stub(isolate);
    716   InstallDescriptor(isolate, &stub);
    717 }
    718 
    719 
    720 void FastNewClosureStub::InstallDescriptors(Isolate* isolate) {
    721   FastNewClosureStub stub(isolate, STRICT, false);
    722   InstallDescriptor(isolate, &stub);
    723 }
    724 
    725 
    726 void FastNewContextStub::InstallDescriptors(Isolate* isolate) {
    727   FastNewContextStub stub(isolate, FastNewContextStub::kMaximumSlots);
    728   InstallDescriptor(isolate, &stub);
    729 }
    730 
    731 
    732 // static
    733 void FastCloneShallowArrayStub::InstallDescriptors(Isolate* isolate) {
    734   FastCloneShallowArrayStub stub(isolate, DONT_TRACK_ALLOCATION_SITE);
    735   InstallDescriptor(isolate, &stub);
    736 }
    737 
    738 
    739 // static
    740 void BinaryOpICStub::InstallDescriptors(Isolate* isolate) {
    741   BinaryOpICStub stub(isolate, Token::ADD, NO_OVERWRITE);
    742   InstallDescriptor(isolate, &stub);
    743 }
    744 
    745 
    746 // static
    747 void BinaryOpWithAllocationSiteStub::InstallDescriptors(Isolate* isolate) {
    748   BinaryOpWithAllocationSiteStub stub(isolate, Token::ADD, NO_OVERWRITE);
    749   InstallDescriptor(isolate, &stub);
    750 }
    751 
    752 
    753 // static
    754 void StringAddStub::InstallDescriptors(Isolate* isolate) {
    755   StringAddStub stub(isolate, STRING_ADD_CHECK_NONE, NOT_TENURED);
    756   InstallDescriptor(isolate, &stub);
    757 }
    758 
    759 
    760 // static
    761 void RegExpConstructResultStub::InstallDescriptors(Isolate* isolate) {
    762   RegExpConstructResultStub stub(isolate);
    763   InstallDescriptor(isolate, &stub);
    764 }
    765 
    766 
    767 // static
    768 void KeyedLoadGenericElementStub::InstallDescriptors(Isolate* isolate) {
    769   KeyedLoadGenericElementStub stub(isolate);
    770   InstallDescriptor(isolate, &stub);
    771 }
    772 
    773 
    774 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
    775     : PlatformCodeStub(isolate), argument_count_(ANY) {
    776   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
    777 }
    778 
    779 
    780 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
    781                                            int argument_count)
    782     : PlatformCodeStub(isolate) {
    783   if (argument_count == 0) {
    784     argument_count_ = NONE;
    785   } else if (argument_count == 1) {
    786     argument_count_ = ONE;
    787   } else if (argument_count >= 2) {
    788     argument_count_ = MORE_THAN_ONE;
    789   } else {
    790     UNREACHABLE();
    791   }
    792   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
    793 }
    794 
    795 
    796 void InternalArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
    797   InternalArrayNoArgumentConstructorStub stub1(isolate, FAST_ELEMENTS);
    798   InstallDescriptor(isolate, &stub1);
    799   InternalArraySingleArgumentConstructorStub stub2(isolate, FAST_ELEMENTS);
    800   InstallDescriptor(isolate, &stub2);
    801   InternalArrayNArgumentsConstructorStub stub3(isolate, FAST_ELEMENTS);
    802   InstallDescriptor(isolate, &stub3);
    803 }
    804 
    805 InternalArrayConstructorStub::InternalArrayConstructorStub(
    806     Isolate* isolate) : PlatformCodeStub(isolate) {
    807   InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
    808 }
    809 
    810 
    811 } }  // namespace v8::internal
    812