Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / v8 / src / code-stubs.cc
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.get()));
84   GDBJIT(AddCode(GDBJITInterface::STUB, name.get(), 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().get(), 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 // static
251 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
252   // Generate special versions of the stub.
253   BinaryOpIC::State::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
254 }
255
256
257 void BinaryOpICWithAllocationSiteStub::PrintState(StringStream* stream) {
258   state_.Print(stream);
259 }
260
261
262 // static
263 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(
264     Isolate* isolate, const BinaryOpIC::State& state) {
265   if (state.CouldCreateAllocationMementos()) {
266     BinaryOpICWithAllocationSiteStub stub(state);
267     stub.GetCode(isolate);
268   }
269 }
270
271
272 void StringAddStub::PrintBaseName(StringStream* stream) {
273   stream->Add("StringAddStub");
274   if ((flags() & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
275     stream->Add("_CheckBoth");
276   } else if ((flags() & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
277     stream->Add("_CheckLeft");
278   } else if ((flags() & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
279     stream->Add("_CheckRight");
280   }
281   if (pretenure_flag() == TENURED) {
282     stream->Add("_Tenured");
283   }
284 }
285
286
287 InlineCacheState ICCompareStub::GetICState() {
288   CompareIC::State state = Max(left_, right_);
289   switch (state) {
290     case CompareIC::UNINITIALIZED:
291       return ::v8::internal::UNINITIALIZED;
292     case CompareIC::SMI:
293     case CompareIC::NUMBER:
294     case CompareIC::INTERNALIZED_STRING:
295     case CompareIC::STRING:
296     case CompareIC::UNIQUE_NAME:
297     case CompareIC::OBJECT:
298     case CompareIC::KNOWN_OBJECT:
299       return MONOMORPHIC;
300     case CompareIC::GENERIC:
301       return ::v8::internal::GENERIC;
302   }
303   UNREACHABLE();
304   return ::v8::internal::UNINITIALIZED;
305 }
306
307
308 void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) {
309   ASSERT(*known_map_ != NULL);
310   Isolate* isolate = new_object->GetIsolate();
311   Factory* factory = isolate->factory();
312   return Map::UpdateCodeCache(known_map_,
313                               strict() ?
314                                   factory->strict_compare_ic_string() :
315                                   factory->compare_ic_string(),
316                               new_object);
317 }
318
319
320 bool ICCompareStub::FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
321   Factory* factory = isolate->factory();
322   Code::Flags flags = Code::ComputeFlags(
323       GetCodeKind(),
324       UNINITIALIZED);
325   ASSERT(op_ == Token::EQ || op_ == Token::EQ_STRICT);
326   Handle<Object> probe(
327       known_map_->FindInCodeCache(
328         strict() ?
329             *factory->strict_compare_ic_string() :
330             *factory->compare_ic_string(),
331         flags),
332       isolate);
333   if (probe->IsCode()) {
334     *code_out = Code::cast(*probe);
335 #ifdef DEBUG
336     Token::Value cached_op;
337     ICCompareStub::DecodeMinorKey((*code_out)->stub_info(), NULL, NULL, NULL,
338                                   &cached_op);
339     ASSERT(op_ == cached_op);
340 #endif
341     return true;
342   }
343   return false;
344 }
345
346
347 int ICCompareStub::MinorKey() {
348   return OpField::encode(op_ - Token::EQ) |
349          LeftStateField::encode(left_) |
350          RightStateField::encode(right_) |
351          HandlerStateField::encode(state_);
352 }
353
354
355 void ICCompareStub::DecodeMinorKey(int minor_key,
356                                    CompareIC::State* left_state,
357                                    CompareIC::State* right_state,
358                                    CompareIC::State* handler_state,
359                                    Token::Value* op) {
360   if (left_state) {
361     *left_state =
362         static_cast<CompareIC::State>(LeftStateField::decode(minor_key));
363   }
364   if (right_state) {
365     *right_state =
366         static_cast<CompareIC::State>(RightStateField::decode(minor_key));
367   }
368   if (handler_state) {
369     *handler_state =
370         static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
371   }
372   if (op) {
373     *op = static_cast<Token::Value>(OpField::decode(minor_key) + Token::EQ);
374   }
375 }
376
377
378 void ICCompareStub::Generate(MacroAssembler* masm) {
379   switch (state_) {
380     case CompareIC::UNINITIALIZED:
381       GenerateMiss(masm);
382       break;
383     case CompareIC::SMI:
384       GenerateSmis(masm);
385       break;
386     case CompareIC::NUMBER:
387       GenerateNumbers(masm);
388       break;
389     case CompareIC::STRING:
390       GenerateStrings(masm);
391       break;
392     case CompareIC::INTERNALIZED_STRING:
393       GenerateInternalizedStrings(masm);
394       break;
395     case CompareIC::UNIQUE_NAME:
396       GenerateUniqueNames(masm);
397       break;
398     case CompareIC::OBJECT:
399       GenerateObjects(masm);
400       break;
401     case CompareIC::KNOWN_OBJECT:
402       ASSERT(*known_map_ != NULL);
403       GenerateKnownObjects(masm);
404       break;
405     case CompareIC::GENERIC:
406       GenerateGeneric(masm);
407       break;
408   }
409 }
410
411
412 void CompareNilICStub::UpdateStatus(Handle<Object> object) {
413   ASSERT(!state_.Contains(GENERIC));
414   State old_state(state_);
415   if (object->IsNull()) {
416     state_.Add(NULL_TYPE);
417   } else if (object->IsUndefined()) {
418     state_.Add(UNDEFINED);
419   } else if (object->IsUndetectableObject() ||
420              object->IsOddball() ||
421              !object->IsHeapObject()) {
422     state_.RemoveAll();
423     state_.Add(GENERIC);
424   } else if (IsMonomorphic()) {
425     state_.RemoveAll();
426     state_.Add(GENERIC);
427   } else {
428     state_.Add(MONOMORPHIC_MAP);
429   }
430   TraceTransition(old_state, state_);
431 }
432
433
434 template<class StateType>
435 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
436   // Note: Although a no-op transition is semantically OK, it is hinting at a
437   // bug somewhere in our state transition machinery.
438   ASSERT(from != to);
439   if (!FLAG_trace_ic) return;
440   char buffer[100];
441   NoAllocationStringAllocator allocator(buffer,
442                                         static_cast<unsigned>(sizeof(buffer)));
443   StringStream stream(&allocator);
444   stream.Add("[");
445   PrintBaseName(&stream);
446   stream.Add(": ");
447   from.Print(&stream);
448   stream.Add("=>");
449   to.Print(&stream);
450   stream.Add("]\n");
451   stream.OutputToStdOut();
452 }
453
454
455 void CompareNilICStub::PrintBaseName(StringStream* stream) {
456   CodeStub::PrintBaseName(stream);
457   stream->Add((nil_value_ == kNullValue) ? "(NullValue)":
458                                            "(UndefinedValue)");
459 }
460
461
462 void CompareNilICStub::PrintState(StringStream* stream) {
463   state_.Print(stream);
464 }
465
466
467 void CompareNilICStub::State::Print(StringStream* stream) const {
468   stream->Add("(");
469   SimpleListPrinter printer(stream);
470   if (IsEmpty()) printer.Add("None");
471   if (Contains(UNDEFINED)) printer.Add("Undefined");
472   if (Contains(NULL_TYPE)) printer.Add("Null");
473   if (Contains(MONOMORPHIC_MAP)) printer.Add("MonomorphicMap");
474   if (Contains(GENERIC)) printer.Add("Generic");
475   stream->Add(")");
476 }
477
478
479 Type* CompareNilICStub::GetType(Zone* zone, Handle<Map> map) {
480   if (state_.Contains(CompareNilICStub::GENERIC)) {
481     return Type::Any(zone);
482   }
483
484   Type* result = Type::None(zone);
485   if (state_.Contains(CompareNilICStub::UNDEFINED)) {
486     result = Type::Union(result, Type::Undefined(zone), zone);
487   }
488   if (state_.Contains(CompareNilICStub::NULL_TYPE)) {
489     result = Type::Union(result, Type::Null(zone), zone);
490   }
491   if (state_.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
492     Type* type =
493         map.is_null() ? Type::Detectable(zone) : Type::Class(map, zone);
494     result = Type::Union(result, type, zone);
495   }
496
497   return result;
498 }
499
500
501 Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
502   Type* output_type = GetType(zone, map);
503   Type* nil_type =
504       nil_value_ == kNullValue ? Type::Null(zone) : Type::Undefined(zone);
505   return Type::Union(output_type, nil_type, zone);
506 }
507
508
509 void InstanceofStub::PrintName(StringStream* stream) {
510   const char* args = "";
511   if (HasArgsInRegisters()) {
512     args = "_REGS";
513   }
514
515   const char* inline_check = "";
516   if (HasCallSiteInlineCheck()) {
517     inline_check = "_INLINE";
518   }
519
520   const char* return_true_false_object = "";
521   if (ReturnTrueFalseObject()) {
522     return_true_false_object = "_TRUEFALSE";
523   }
524
525   stream->Add("InstanceofStub%s%s%s",
526               args,
527               inline_check,
528               return_true_false_object);
529 }
530
531
532 void JSEntryStub::FinishCode(Handle<Code> code) {
533   Handle<FixedArray> handler_table =
534       code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
535   handler_table->set(0, Smi::FromInt(handler_offset_));
536   code->set_handler_table(*handler_table);
537 }
538
539
540 void KeyedLoadDictionaryElementPlatformStub::Generate(
541     MacroAssembler* masm) {
542   KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm);
543 }
544
545
546 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
547   CreateAllocationSiteStub stub;
548   stub.GetCode(isolate);
549 }
550
551
552 void KeyedStoreElementStub::Generate(MacroAssembler* masm) {
553   switch (elements_kind_) {
554     case FAST_ELEMENTS:
555     case FAST_HOLEY_ELEMENTS:
556     case FAST_SMI_ELEMENTS:
557     case FAST_HOLEY_SMI_ELEMENTS:
558     case FAST_DOUBLE_ELEMENTS:
559     case FAST_HOLEY_DOUBLE_ELEMENTS:
560 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
561     case EXTERNAL_##TYPE##_ELEMENTS:                    \
562     case TYPE##_ELEMENTS:
563
564     TYPED_ARRAYS(TYPED_ARRAY_CASE)
565 #undef TYPED_ARRAY_CASE
566       UNREACHABLE();
567       break;
568     case DICTIONARY_ELEMENTS:
569       KeyedStoreStubCompiler::GenerateStoreDictionaryElement(masm);
570       break;
571     case NON_STRICT_ARGUMENTS_ELEMENTS:
572       UNREACHABLE();
573       break;
574   }
575 }
576
577
578 void ArgumentsAccessStub::PrintName(StringStream* stream) {
579   stream->Add("ArgumentsAccessStub_");
580   switch (type_) {
581     case READ_ELEMENT: stream->Add("ReadElement"); break;
582     case NEW_NON_STRICT_FAST: stream->Add("NewNonStrictFast"); break;
583     case NEW_NON_STRICT_SLOW: stream->Add("NewNonStrictSlow"); break;
584     case NEW_STRICT: stream->Add("NewStrict"); break;
585   }
586 }
587
588
589 void CallFunctionStub::PrintName(StringStream* stream) {
590   stream->Add("CallFunctionStub_Args%d", argc_);
591   if (RecordCallTarget()) stream->Add("_Recording");
592 }
593
594
595 void CallConstructStub::PrintName(StringStream* stream) {
596   stream->Add("CallConstructStub");
597   if (RecordCallTarget()) stream->Add("_Recording");
598 }
599
600
601 void ArrayConstructorStub::PrintName(StringStream* stream) {
602   stream->Add("ArrayConstructorStub");
603   switch (argument_count_) {
604     case ANY: stream->Add("_Any"); break;
605     case NONE: stream->Add("_None"); break;
606     case ONE: stream->Add("_One"); break;
607     case MORE_THAN_ONE: stream->Add("_More_Than_One"); break;
608   }
609 }
610
611
612 void ArrayConstructorStubBase::BasePrintName(const char* name,
613                                              StringStream* stream) {
614   stream->Add(name);
615   stream->Add("_");
616   stream->Add(ElementsKindToString(elements_kind()));
617   if (override_mode() == DISABLE_ALLOCATION_SITES) {
618     stream->Add("_DISABLE_ALLOCATION_SITES");
619   }
620 }
621
622
623 bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
624   Types old_types(types_);
625   bool to_boolean_value = types_.UpdateStatus(object);
626   TraceTransition(old_types, types_);
627   return to_boolean_value;
628 }
629
630
631 void ToBooleanStub::PrintState(StringStream* stream) {
632   types_.Print(stream);
633 }
634
635
636 void ToBooleanStub::Types::Print(StringStream* stream) const {
637   stream->Add("(");
638   SimpleListPrinter printer(stream);
639   if (IsEmpty()) printer.Add("None");
640   if (Contains(UNDEFINED)) printer.Add("Undefined");
641   if (Contains(BOOLEAN)) printer.Add("Bool");
642   if (Contains(NULL_TYPE)) printer.Add("Null");
643   if (Contains(SMI)) printer.Add("Smi");
644   if (Contains(SPEC_OBJECT)) printer.Add("SpecObject");
645   if (Contains(STRING)) printer.Add("String");
646   if (Contains(SYMBOL)) printer.Add("Symbol");
647   if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber");
648   stream->Add(")");
649 }
650
651
652 bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
653   if (object->IsUndefined()) {
654     Add(UNDEFINED);
655     return false;
656   } else if (object->IsBoolean()) {
657     Add(BOOLEAN);
658     return object->IsTrue();
659   } else if (object->IsNull()) {
660     Add(NULL_TYPE);
661     return false;
662   } else if (object->IsSmi()) {
663     Add(SMI);
664     return Smi::cast(*object)->value() != 0;
665   } else if (object->IsSpecObject()) {
666     Add(SPEC_OBJECT);
667     return !object->IsUndetectableObject();
668   } else if (object->IsString()) {
669     Add(STRING);
670     return !object->IsUndetectableObject() &&
671         String::cast(*object)->length() != 0;
672   } else if (object->IsSymbol()) {
673     Add(SYMBOL);
674     return true;
675   } else if (object->IsHeapNumber()) {
676     ASSERT(!object->IsUndetectableObject());
677     Add(HEAP_NUMBER);
678     double value = HeapNumber::cast(*object)->value();
679     return value != 0 && !std::isnan(value);
680   } else {
681     // We should never see an internal object at runtime here!
682     UNREACHABLE();
683     return true;
684   }
685 }
686
687
688 bool ToBooleanStub::Types::NeedsMap() const {
689   return Contains(ToBooleanStub::SPEC_OBJECT)
690       || Contains(ToBooleanStub::STRING)
691       || Contains(ToBooleanStub::SYMBOL)
692       || Contains(ToBooleanStub::HEAP_NUMBER);
693 }
694
695
696 bool ToBooleanStub::Types::CanBeUndetectable() const {
697   return Contains(ToBooleanStub::SPEC_OBJECT)
698       || Contains(ToBooleanStub::STRING);
699 }
700
701
702 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
703   StubFailureTrampolineStub stub1(NOT_JS_FUNCTION_STUB_MODE);
704   StubFailureTrampolineStub stub2(JS_FUNCTION_STUB_MODE);
705   stub1.GetCode(isolate);
706   stub2.GetCode(isolate);
707 }
708
709
710 void StubFailureTailCallTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
711   StubFailureTailCallTrampolineStub stub;
712   stub.GetCode(isolate);
713 }
714
715
716 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
717                                                intptr_t stack_pointer,
718                                                Isolate* isolate) {
719   FunctionEntryHook entry_hook = isolate->function_entry_hook();
720   ASSERT(entry_hook != NULL);
721   entry_hook(function, stack_pointer);
722 }
723
724
725 static void InstallDescriptor(Isolate* isolate, HydrogenCodeStub* stub) {
726   int major_key = stub->MajorKey();
727   CodeStubInterfaceDescriptor* descriptor =
728       isolate->code_stub_interface_descriptor(major_key);
729   if (!descriptor->initialized()) {
730     stub->InitializeInterfaceDescriptor(isolate, descriptor);
731   }
732 }
733
734
735 void ArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
736   ArrayNoArgumentConstructorStub stub1(GetInitialFastElementsKind());
737   InstallDescriptor(isolate, &stub1);
738   ArraySingleArgumentConstructorStub stub2(GetInitialFastElementsKind());
739   InstallDescriptor(isolate, &stub2);
740   ArrayNArgumentsConstructorStub stub3(GetInitialFastElementsKind());
741   InstallDescriptor(isolate, &stub3);
742 }
743
744
745 void NumberToStringStub::InstallDescriptors(Isolate* isolate) {
746   NumberToStringStub stub;
747   InstallDescriptor(isolate, &stub);
748 }
749
750
751 void FastNewClosureStub::InstallDescriptors(Isolate* isolate) {
752   FastNewClosureStub stub(STRICT_MODE, false);
753   InstallDescriptor(isolate, &stub);
754 }
755
756
757 void FastNewContextStub::InstallDescriptors(Isolate* isolate) {
758   FastNewContextStub stub(FastNewContextStub::kMaximumSlots);
759   InstallDescriptor(isolate, &stub);
760 }
761
762
763 // static
764 void BinaryOpICStub::InstallDescriptors(Isolate* isolate) {
765   BinaryOpICStub stub(Token::ADD, NO_OVERWRITE);
766   InstallDescriptor(isolate, &stub);
767 }
768
769
770 // static
771 void BinaryOpWithAllocationSiteStub::InstallDescriptors(Isolate* isolate) {
772   BinaryOpWithAllocationSiteStub stub(Token::ADD, NO_OVERWRITE);
773   InstallDescriptor(isolate, &stub);
774 }
775
776
777 // static
778 void StringAddStub::InstallDescriptors(Isolate* isolate) {
779   StringAddStub stub(STRING_ADD_CHECK_NONE, NOT_TENURED);
780   InstallDescriptor(isolate, &stub);
781 }
782
783
784 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
785     : argument_count_(ANY) {
786   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
787 }
788
789
790 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
791                                            int argument_count) {
792   if (argument_count == 0) {
793     argument_count_ = NONE;
794   } else if (argument_count == 1) {
795     argument_count_ = ONE;
796   } else if (argument_count >= 2) {
797     argument_count_ = MORE_THAN_ONE;
798   } else {
799     UNREACHABLE();
800   }
801   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
802 }
803
804
805 void InternalArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
806   InternalArrayNoArgumentConstructorStub stub1(FAST_ELEMENTS);
807   InstallDescriptor(isolate, &stub1);
808   InternalArraySingleArgumentConstructorStub stub2(FAST_ELEMENTS);
809   InstallDescriptor(isolate, &stub2);
810   InternalArrayNArgumentsConstructorStub stub3(FAST_ELEMENTS);
811   InstallDescriptor(isolate, &stub3);
812 }
813
814 InternalArrayConstructorStub::InternalArrayConstructorStub(
815     Isolate* isolate) {
816   InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
817 }
818
819
820 } }  // namespace v8::internal