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