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