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