• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CodeStubInterfaceDescriptor()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 
FindCodeInCache(Code ** code_out)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 
GetName()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 
RecordCodeGeneration(Handle<Code> code)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 
GetCodeKind() const63 Code::Kind CodeStub::GetCodeKind() const {
64   return Code::STUB;
65 }
66 
67 
GetCodeCopy(const Code::FindAndReplacePattern & pattern)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 
GenerateCode()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 
GetCode()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 
MajorName(CodeStub::Major major_key,bool allow_unknown_keys)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 
PrintBaseName(StringStream * stream)173 void CodeStub::PrintBaseName(StringStream* stream) {
174   stream->Add("%s", MajorName(MajorKey(), false));
175 }
176 
177 
PrintName(StringStream * stream)178 void CodeStub::PrintName(StringStream* stream) {
179   PrintBaseName(stream);
180   PrintState(stream);
181 }
182 
183 
184 // static
GenerateAheadOfTime(Isolate * isolate)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 
PrintState(StringStream * stream)201 void BinaryOpICStub::PrintState(StringStream* stream) {
202   state_.Print(stream);
203 }
204 
205 
206 // static
GenerateAheadOfTime(Isolate * isolate,const BinaryOpIC::State & state)207 void BinaryOpICStub::GenerateAheadOfTime(Isolate* isolate,
208                                          const BinaryOpIC::State& state) {
209   BinaryOpICStub stub(isolate, state);
210   stub.GetCode();
211 }
212 
213 
214 // static
GenerateAheadOfTime(Isolate * isolate)215 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
216   // Generate special versions of the stub.
217   BinaryOpIC::State::GenerateAheadOfTime(isolate, &GenerateAheadOfTime);
218 }
219 
220 
PrintState(StringStream * stream)221 void BinaryOpICWithAllocationSiteStub::PrintState(StringStream* stream) {
222   state_.Print(stream);
223 }
224 
225 
226 // static
GenerateAheadOfTime(Isolate * isolate,const BinaryOpIC::State & state)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 
PrintBaseName(StringStream * stream)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 
GetICState()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 
AddToSpecialCache(Handle<Code> new_object)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 
FindCodeInSpecialCache(Code ** code_out)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 
MinorKey()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 
DecodeMinorKey(int minor_key,CompareIC::State * left_state,CompareIC::State * right_state,CompareIC::State * handler_state,Token::Value * op)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 
Generate(MacroAssembler * masm)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 
UpdateStatus(Handle<Object> object)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>
TraceTransition(StateType from,StateType to)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 
PrintBaseName(StringStream * stream)419 void CompareNilICStub::PrintBaseName(StringStream* stream) {
420   CodeStub::PrintBaseName(stream);
421   stream->Add((nil_value_ == kNullValue) ? "(NullValue)":
422                                            "(UndefinedValue)");
423 }
424 
425 
PrintState(StringStream * stream)426 void CompareNilICStub::PrintState(StringStream* stream) {
427   state_.Print(stream);
428 }
429 
430 
Print(StringStream * stream) const431 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 
GetType(Zone * zone,Handle<Map> map)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 
GetInputType(Zone * zone,Handle<Map> map)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 
PrintState(StringStream * stream)473 void CallIC_ArrayStub::PrintState(StringStream* stream) {
474   state_.Print(stream);
475   stream->Add(" (Array)");
476 }
477 
478 
PrintState(StringStream * stream)479 void CallICStub::PrintState(StringStream* stream) {
480   state_.Print(stream);
481 }
482 
483 
PrintName(StringStream * stream)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 
FinishCode(Handle<Code> code)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 
Generate(MacroAssembler * masm)515 void KeyedLoadDictionaryElementPlatformStub::Generate(
516     MacroAssembler* masm) {
517   KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm);
518 }
519 
520 
GenerateAheadOfTime(Isolate * isolate)521 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
522   CreateAllocationSiteStub stub(isolate);
523   stub.GetCode();
524 }
525 
526 
Generate(MacroAssembler * masm)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 
PrintName(StringStream * stream)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 
PrintName(StringStream * stream)564 void CallFunctionStub::PrintName(StringStream* stream) {
565   stream->Add("CallFunctionStub_Args%d", argc_);
566 }
567 
568 
PrintName(StringStream * stream)569 void CallConstructStub::PrintName(StringStream* stream) {
570   stream->Add("CallConstructStub");
571   if (RecordCallTarget()) stream->Add("_Recording");
572 }
573 
574 
PrintName(StringStream * stream)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 
BasePrintName(const char * name,StringStream * stream)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 
UpdateStatus(Handle<Object> object)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 
PrintState(StringStream * stream)605 void ToBooleanStub::PrintState(StringStream* stream) {
606   types_.Print(stream);
607 }
608 
609 
Print(StringStream * stream) const610 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 
UpdateStatus(Handle<Object> object)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 
NeedsMap() const662 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 
CanBeUndetectable() const670 bool ToBooleanStub::Types::CanBeUndetectable() const {
671   return Contains(ToBooleanStub::SPEC_OBJECT)
672       || Contains(ToBooleanStub::STRING);
673 }
674 
675 
GenerateAheadOfTime(Isolate * isolate)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 
EntryHookTrampoline(intptr_t function,intptr_t stack_pointer,Isolate * isolate)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 
InstallDescriptor(Isolate * isolate,HydrogenCodeStub * stub)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 
InstallDescriptors(Isolate * isolate)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 
InstallDescriptors(Isolate * isolate)714 void NumberToStringStub::InstallDescriptors(Isolate* isolate) {
715   NumberToStringStub stub(isolate);
716   InstallDescriptor(isolate, &stub);
717 }
718 
719 
InstallDescriptors(Isolate * isolate)720 void FastNewClosureStub::InstallDescriptors(Isolate* isolate) {
721   FastNewClosureStub stub(isolate, STRICT, false);
722   InstallDescriptor(isolate, &stub);
723 }
724 
725 
InstallDescriptors(Isolate * isolate)726 void FastNewContextStub::InstallDescriptors(Isolate* isolate) {
727   FastNewContextStub stub(isolate, FastNewContextStub::kMaximumSlots);
728   InstallDescriptor(isolate, &stub);
729 }
730 
731 
732 // static
InstallDescriptors(Isolate * isolate)733 void FastCloneShallowArrayStub::InstallDescriptors(Isolate* isolate) {
734   FastCloneShallowArrayStub stub(isolate, DONT_TRACK_ALLOCATION_SITE);
735   InstallDescriptor(isolate, &stub);
736 }
737 
738 
739 // static
InstallDescriptors(Isolate * isolate)740 void BinaryOpICStub::InstallDescriptors(Isolate* isolate) {
741   BinaryOpICStub stub(isolate, Token::ADD, NO_OVERWRITE);
742   InstallDescriptor(isolate, &stub);
743 }
744 
745 
746 // static
InstallDescriptors(Isolate * isolate)747 void BinaryOpWithAllocationSiteStub::InstallDescriptors(Isolate* isolate) {
748   BinaryOpWithAllocationSiteStub stub(isolate, Token::ADD, NO_OVERWRITE);
749   InstallDescriptor(isolate, &stub);
750 }
751 
752 
753 // static
InstallDescriptors(Isolate * isolate)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
InstallDescriptors(Isolate * isolate)761 void RegExpConstructResultStub::InstallDescriptors(Isolate* isolate) {
762   RegExpConstructResultStub stub(isolate);
763   InstallDescriptor(isolate, &stub);
764 }
765 
766 
767 // static
InstallDescriptors(Isolate * isolate)768 void KeyedLoadGenericElementStub::InstallDescriptors(Isolate* isolate) {
769   KeyedLoadGenericElementStub stub(isolate);
770   InstallDescriptor(isolate, &stub);
771 }
772 
773 
ArrayConstructorStub(Isolate * isolate)774 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
775     : PlatformCodeStub(isolate), argument_count_(ANY) {
776   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
777 }
778 
779 
ArrayConstructorStub(Isolate * isolate,int argument_count)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 
InstallDescriptors(Isolate * isolate)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 
InternalArrayConstructorStub(Isolate * isolate)805 InternalArrayConstructorStub::InternalArrayConstructorStub(
806     Isolate* isolate) : PlatformCodeStub(isolate) {
807   InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
808 }
809 
810 
811 } }  // namespace v8::internal
812