| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 code = compiler.CompileStoreField(receiver, field_index, transition, name); | 434 code = compiler.CompileStoreField(receiver, field_index, transition, name); |
| 435 if (code->IsFailure()) return code; | 435 if (code->IsFailure()) return code; |
| 436 PROFILE(CodeCreateEvent( | 436 PROFILE(CodeCreateEvent( |
| 437 Logger::KEYED_STORE_IC_TAG, Code::cast(code), name)); | 437 Logger::KEYED_STORE_IC_TAG, Code::cast(code), name)); |
| 438 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 438 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); |
| 439 if (result->IsFailure()) return result; | 439 if (result->IsFailure()) return result; |
| 440 } | 440 } |
| 441 return code; | 441 return code; |
| 442 } | 442 } |
| 443 | 443 |
| 444 #define CALL_LOGGER_TAG(kind, type) \ |
| 445 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) |
| 444 | 446 |
| 445 Object* StubCache::ComputeCallConstant(int argc, | 447 Object* StubCache::ComputeCallConstant(int argc, |
| 446 InLoopFlag in_loop, | 448 InLoopFlag in_loop, |
| 449 Code::Kind kind, |
| 447 String* name, | 450 String* name, |
| 448 Object* object, | 451 Object* object, |
| 449 JSObject* holder, | 452 JSObject* holder, |
| 450 JSFunction* function) { | 453 JSFunction* function) { |
| 451 // Compute the check type and the map. | 454 // Compute the check type and the map. |
| 452 Map* map = IC::GetCodeCacheMapForObject(object); | 455 Map* map = IC::GetCodeCacheMapForObject(object); |
| 453 | 456 |
| 454 // Compute check type based on receiver/holder. | 457 // Compute check type based on receiver/holder. |
| 455 StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK; | 458 StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK; |
| 456 if (object->IsString()) { | 459 if (object->IsString()) { |
| 457 check = StubCompiler::STRING_CHECK; | 460 check = StubCompiler::STRING_CHECK; |
| 458 } else if (object->IsNumber()) { | 461 } else if (object->IsNumber()) { |
| 459 check = StubCompiler::NUMBER_CHECK; | 462 check = StubCompiler::NUMBER_CHECK; |
| 460 } else if (object->IsBoolean()) { | 463 } else if (object->IsBoolean()) { |
| 461 check = StubCompiler::BOOLEAN_CHECK; | 464 check = StubCompiler::BOOLEAN_CHECK; |
| 462 } | 465 } |
| 463 | 466 |
| 464 Code::Flags flags = | 467 Code::Flags flags = |
| 465 Code::ComputeMonomorphicFlags(Code::CALL_IC, | 468 Code::ComputeMonomorphicFlags(kind, |
| 466 CONSTANT_FUNCTION, | 469 CONSTANT_FUNCTION, |
| 467 in_loop, | 470 in_loop, |
| 468 argc); | 471 argc); |
| 469 Object* code = map->FindInCodeCache(name, flags); | 472 Object* code = map->FindInCodeCache(name, flags); |
| 470 if (code->IsUndefined()) { | 473 if (code->IsUndefined()) { |
| 471 // If the function hasn't been compiled yet, we cannot do it now | 474 // If the function hasn't been compiled yet, we cannot do it now |
| 472 // because it may cause GC. To avoid this issue, we return an | 475 // because it may cause GC. To avoid this issue, we return an |
| 473 // internal error which will make sure we do not update any | 476 // internal error which will make sure we do not update any |
| 474 // caches. | 477 // caches. |
| 475 if (!function->is_compiled()) return Failure::InternalError(); | 478 if (!function->is_compiled()) return Failure::InternalError(); |
| 476 // Compile the stub - only create stubs for fully compiled functions. | 479 // Compile the stub - only create stubs for fully compiled functions. |
| 477 CallStubCompiler compiler(argc, in_loop); | 480 CallStubCompiler compiler(argc, in_loop, kind); |
| 478 code = compiler.CompileCallConstant(object, holder, function, name, check); | 481 code = compiler.CompileCallConstant(object, holder, function, name, check); |
| 479 if (code->IsFailure()) return code; | 482 if (code->IsFailure()) return code; |
| 480 ASSERT_EQ(flags, Code::cast(code)->flags()); | 483 ASSERT_EQ(flags, Code::cast(code)->flags()); |
| 481 PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 484 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 485 Code::cast(code), name)); |
| 482 Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 486 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
| 483 if (result->IsFailure()) return result; | 487 if (result->IsFailure()) return result; |
| 484 } | 488 } |
| 485 return Set(name, map, Code::cast(code)); | 489 return Set(name, map, Code::cast(code)); |
| 486 } | 490 } |
| 487 | 491 |
| 488 | 492 |
| 489 Object* StubCache::ComputeCallField(int argc, | 493 Object* StubCache::ComputeCallField(int argc, |
| 490 InLoopFlag in_loop, | 494 InLoopFlag in_loop, |
| 495 Code::Kind kind, |
| 491 String* name, | 496 String* name, |
| 492 Object* object, | 497 Object* object, |
| 493 JSObject* holder, | 498 JSObject* holder, |
| 494 int index) { | 499 int index) { |
| 495 // Compute the check type and the map. | 500 // Compute the check type and the map. |
| 496 Map* map = IC::GetCodeCacheMapForObject(object); | 501 Map* map = IC::GetCodeCacheMapForObject(object); |
| 497 | 502 |
| 498 // TODO(1233596): We cannot do receiver map check for non-JS objects | 503 // TODO(1233596): We cannot do receiver map check for non-JS objects |
| 499 // because they may be represented as immediates without a | 504 // because they may be represented as immediates without a |
| 500 // map. Instead, we check against the map in the holder. | 505 // map. Instead, we check against the map in the holder. |
| 501 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 506 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { |
| 502 object = holder; | 507 object = holder; |
| 503 } | 508 } |
| 504 | 509 |
| 505 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 510 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, |
| 506 FIELD, | 511 FIELD, |
| 507 in_loop, | 512 in_loop, |
| 508 argc); | 513 argc); |
| 509 Object* code = map->FindInCodeCache(name, flags); | 514 Object* code = map->FindInCodeCache(name, flags); |
| 510 if (code->IsUndefined()) { | 515 if (code->IsUndefined()) { |
| 511 CallStubCompiler compiler(argc, in_loop); | 516 CallStubCompiler compiler(argc, in_loop, kind); |
| 512 code = compiler.CompileCallField(JSObject::cast(object), | 517 code = compiler.CompileCallField(JSObject::cast(object), |
| 513 holder, | 518 holder, |
| 514 index, | 519 index, |
| 515 name); | 520 name); |
| 516 if (code->IsFailure()) return code; | 521 if (code->IsFailure()) return code; |
| 517 ASSERT_EQ(flags, Code::cast(code)->flags()); | 522 ASSERT_EQ(flags, Code::cast(code)->flags()); |
| 518 PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 523 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 524 Code::cast(code), name)); |
| 519 Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 525 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
| 520 if (result->IsFailure()) return result; | 526 if (result->IsFailure()) return result; |
| 521 } | 527 } |
| 522 return Set(name, map, Code::cast(code)); | 528 return Set(name, map, Code::cast(code)); |
| 523 } | 529 } |
| 524 | 530 |
| 525 | 531 |
| 526 Object* StubCache::ComputeCallInterceptor(int argc, | 532 Object* StubCache::ComputeCallInterceptor(int argc, |
| 533 Code::Kind kind, |
| 527 String* name, | 534 String* name, |
| 528 Object* object, | 535 Object* object, |
| 529 JSObject* holder) { | 536 JSObject* holder) { |
| 530 // Compute the check type and the map. | 537 // Compute the check type and the map. |
| 531 // If the object is a value, we use the prototype map for the cache. | 538 // If the object is a value, we use the prototype map for the cache. |
| 532 Map* map = IC::GetCodeCacheMapForObject(object); | 539 Map* map = IC::GetCodeCacheMapForObject(object); |
| 533 | 540 |
| 534 // TODO(1233596): We cannot do receiver map check for non-JS objects | 541 // TODO(1233596): We cannot do receiver map check for non-JS objects |
| 535 // because they may be represented as immediates without a | 542 // because they may be represented as immediates without a |
| 536 // map. Instead, we check against the map in the holder. | 543 // map. Instead, we check against the map in the holder. |
| 537 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 544 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { |
| 538 object = holder; | 545 object = holder; |
| 539 } | 546 } |
| 540 | 547 |
| 541 Code::Flags flags = | 548 Code::Flags flags = |
| 542 Code::ComputeMonomorphicFlags(Code::CALL_IC, | 549 Code::ComputeMonomorphicFlags(kind, |
| 543 INTERCEPTOR, | 550 INTERCEPTOR, |
| 544 NOT_IN_LOOP, | 551 NOT_IN_LOOP, |
| 545 argc); | 552 argc); |
| 546 Object* code = map->FindInCodeCache(name, flags); | 553 Object* code = map->FindInCodeCache(name, flags); |
| 547 if (code->IsUndefined()) { | 554 if (code->IsUndefined()) { |
| 548 CallStubCompiler compiler(argc, NOT_IN_LOOP); | 555 CallStubCompiler compiler(argc, NOT_IN_LOOP, kind); |
| 549 code = compiler.CompileCallInterceptor(JSObject::cast(object), | 556 code = compiler.CompileCallInterceptor(JSObject::cast(object), |
| 550 holder, | 557 holder, |
| 551 name); | 558 name); |
| 552 if (code->IsFailure()) return code; | 559 if (code->IsFailure()) return code; |
| 553 ASSERT_EQ(flags, Code::cast(code)->flags()); | 560 ASSERT_EQ(flags, Code::cast(code)->flags()); |
| 554 PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 561 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 562 Code::cast(code), name)); |
| 555 Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 563 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
| 556 if (result->IsFailure()) return result; | 564 if (result->IsFailure()) return result; |
| 557 } | 565 } |
| 558 return Set(name, map, Code::cast(code)); | 566 return Set(name, map, Code::cast(code)); |
| 559 } | 567 } |
| 560 | 568 |
| 561 | 569 |
| 562 Object* StubCache::ComputeCallNormal(int argc, | 570 Object* StubCache::ComputeCallNormal(int argc, |
| 563 InLoopFlag in_loop, | 571 InLoopFlag in_loop, |
| 572 Code::Kind kind, |
| 564 String* name, | 573 String* name, |
| 565 JSObject* receiver) { | 574 JSObject* receiver) { |
| 566 Object* code = ComputeCallNormal(argc, in_loop); | 575 Object* code = ComputeCallNormal(argc, in_loop, kind); |
| 567 if (code->IsFailure()) return code; | 576 if (code->IsFailure()) return code; |
| 568 return Set(name, receiver->map(), Code::cast(code)); | 577 return Set(name, receiver->map(), Code::cast(code)); |
| 569 } | 578 } |
| 570 | 579 |
| 571 | 580 |
| 572 Object* StubCache::ComputeCallGlobal(int argc, | 581 Object* StubCache::ComputeCallGlobal(int argc, |
| 573 InLoopFlag in_loop, | 582 InLoopFlag in_loop, |
| 583 Code::Kind kind, |
| 574 String* name, | 584 String* name, |
| 575 JSObject* receiver, | 585 JSObject* receiver, |
| 576 GlobalObject* holder, | 586 GlobalObject* holder, |
| 577 JSGlobalPropertyCell* cell, | 587 JSGlobalPropertyCell* cell, |
| 578 JSFunction* function) { | 588 JSFunction* function) { |
| 579 Code::Flags flags = | 589 Code::Flags flags = |
| 580 Code::ComputeMonomorphicFlags(Code::CALL_IC, NORMAL, in_loop, argc); | 590 Code::ComputeMonomorphicFlags(kind, |
| 591 NORMAL, |
| 592 in_loop, |
| 593 argc); |
| 581 Object* code = receiver->map()->FindInCodeCache(name, flags); | 594 Object* code = receiver->map()->FindInCodeCache(name, flags); |
| 582 if (code->IsUndefined()) { | 595 if (code->IsUndefined()) { |
| 583 // If the function hasn't been compiled yet, we cannot do it now | 596 // If the function hasn't been compiled yet, we cannot do it now |
| 584 // because it may cause GC. To avoid this issue, we return an | 597 // because it may cause GC. To avoid this issue, we return an |
| 585 // internal error which will make sure we do not update any | 598 // internal error which will make sure we do not update any |
| 586 // caches. | 599 // caches. |
| 587 if (!function->is_compiled()) return Failure::InternalError(); | 600 if (!function->is_compiled()) return Failure::InternalError(); |
| 588 CallStubCompiler compiler(argc, in_loop); | 601 CallStubCompiler compiler(argc, in_loop, kind); |
| 589 code = compiler.CompileCallGlobal(receiver, holder, cell, function, name); | 602 code = compiler.CompileCallGlobal(receiver, holder, cell, function, name); |
| 590 if (code->IsFailure()) return code; | 603 if (code->IsFailure()) return code; |
| 591 ASSERT_EQ(flags, Code::cast(code)->flags()); | 604 ASSERT_EQ(flags, Code::cast(code)->flags()); |
| 592 PROFILE(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); | 605 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
| 606 Code::cast(code), name)); |
| 593 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 607 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); |
| 594 if (result->IsFailure()) return result; | 608 if (result->IsFailure()) return result; |
| 595 } | 609 } |
| 596 return Set(name, receiver->map(), Code::cast(code)); | 610 return Set(name, receiver->map(), Code::cast(code)); |
| 597 } | 611 } |
| 598 | 612 |
| 599 | 613 |
| 600 static Object* GetProbeValue(Code::Flags flags) { | 614 static Object* GetProbeValue(Code::Flags flags) { |
| 601 // Use raw_unchecked... so we don't get assert failures during GC. | 615 // Use raw_unchecked... so we don't get assert failures during GC. |
| 602 NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache(); | 616 NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 630 ASSERT(entry != -1); | 644 ASSERT(entry != -1); |
| 631 ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) == | 645 ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) == |
| 632 Heap::undefined_value()); | 646 Heap::undefined_value()); |
| 633 Heap::non_monomorphic_cache()->ValueAtPut(entry, code); | 647 Heap::non_monomorphic_cache()->ValueAtPut(entry, code); |
| 634 CHECK(GetProbeValue(Code::cast(code)->flags()) == code); | 648 CHECK(GetProbeValue(Code::cast(code)->flags()) == code); |
| 635 } | 649 } |
| 636 return code; | 650 return code; |
| 637 } | 651 } |
| 638 | 652 |
| 639 | 653 |
| 640 Code* StubCache::FindCallInitialize(int argc, InLoopFlag in_loop) { | 654 Code* StubCache::FindCallInitialize(int argc, |
| 655 InLoopFlag in_loop, |
| 656 Code::Kind kind) { |
| 641 Code::Flags flags = | 657 Code::Flags flags = |
| 642 Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc); | 658 Code::ComputeFlags(kind, in_loop, UNINITIALIZED, NORMAL, argc); |
| 643 Object* result = ProbeCache(flags); | 659 Object* result = ProbeCache(flags); |
| 644 ASSERT(!result->IsUndefined()); | 660 ASSERT(!result->IsUndefined()); |
| 645 // This might be called during the marking phase of the collector | 661 // This might be called during the marking phase of the collector |
| 646 // hence the unchecked cast. | 662 // hence the unchecked cast. |
| 647 return reinterpret_cast<Code*>(result); | 663 return reinterpret_cast<Code*>(result); |
| 648 } | 664 } |
| 649 | 665 |
| 650 | 666 |
| 651 Object* StubCache::ComputeCallInitialize(int argc, InLoopFlag in_loop) { | 667 Object* StubCache::ComputeCallInitialize(int argc, |
| 668 InLoopFlag in_loop, |
| 669 Code::Kind kind) { |
| 652 Code::Flags flags = | 670 Code::Flags flags = |
| 653 Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc); | 671 Code::ComputeFlags(kind, in_loop, UNINITIALIZED, NORMAL, argc); |
| 654 Object* probe = ProbeCache(flags); | 672 Object* probe = ProbeCache(flags); |
| 655 if (!probe->IsUndefined()) return probe; | 673 if (!probe->IsUndefined()) return probe; |
| 656 StubCompiler compiler; | 674 StubCompiler compiler; |
| 657 return FillCache(compiler.CompileCallInitialize(flags)); | 675 return FillCache(compiler.CompileCallInitialize(flags)); |
| 658 } | 676 } |
| 659 | 677 |
| 660 | 678 |
| 661 Object* StubCache::ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop) { | 679 Object* StubCache::ComputeCallPreMonomorphic(int argc, |
| 680 InLoopFlag in_loop, |
| 681 Code::Kind kind) { |
| 662 Code::Flags flags = | 682 Code::Flags flags = |
| 663 Code::ComputeFlags(Code::CALL_IC, in_loop, PREMONOMORPHIC, NORMAL, argc); | 683 Code::ComputeFlags(kind, in_loop, PREMONOMORPHIC, NORMAL, argc); |
| 664 Object* probe = ProbeCache(flags); | 684 Object* probe = ProbeCache(flags); |
| 665 if (!probe->IsUndefined()) return probe; | 685 if (!probe->IsUndefined()) return probe; |
| 666 StubCompiler compiler; | 686 StubCompiler compiler; |
| 667 return FillCache(compiler.CompileCallPreMonomorphic(flags)); | 687 return FillCache(compiler.CompileCallPreMonomorphic(flags)); |
| 668 } | 688 } |
| 669 | 689 |
| 670 | 690 |
| 671 Object* StubCache::ComputeCallNormal(int argc, InLoopFlag in_loop) { | 691 Object* StubCache::ComputeCallNormal(int argc, |
| 692 InLoopFlag in_loop, |
| 693 Code::Kind kind) { |
| 672 Code::Flags flags = | 694 Code::Flags flags = |
| 673 Code::ComputeFlags(Code::CALL_IC, in_loop, MONOMORPHIC, NORMAL, argc); | 695 Code::ComputeFlags(kind, in_loop, MONOMORPHIC, NORMAL, argc); |
| 674 Object* probe = ProbeCache(flags); | 696 Object* probe = ProbeCache(flags); |
| 675 if (!probe->IsUndefined()) return probe; | 697 if (!probe->IsUndefined()) return probe; |
| 676 StubCompiler compiler; | 698 StubCompiler compiler; |
| 677 return FillCache(compiler.CompileCallNormal(flags)); | 699 return FillCache(compiler.CompileCallNormal(flags)); |
| 678 } | 700 } |
| 679 | 701 |
| 680 | 702 |
| 681 Object* StubCache::ComputeCallMegamorphic(int argc, InLoopFlag in_loop) { | 703 Object* StubCache::ComputeCallMegamorphic(int argc, |
| 704 InLoopFlag in_loop, |
| 705 Code::Kind kind) { |
| 682 Code::Flags flags = | 706 Code::Flags flags = |
| 683 Code::ComputeFlags(Code::CALL_IC, in_loop, MEGAMORPHIC, NORMAL, argc); | 707 Code::ComputeFlags(kind, in_loop, MEGAMORPHIC, NORMAL, argc); |
| 684 Object* probe = ProbeCache(flags); | 708 Object* probe = ProbeCache(flags); |
| 685 if (!probe->IsUndefined()) return probe; | 709 if (!probe->IsUndefined()) return probe; |
| 686 StubCompiler compiler; | 710 StubCompiler compiler; |
| 687 return FillCache(compiler.CompileCallMegamorphic(flags)); | 711 return FillCache(compiler.CompileCallMegamorphic(flags)); |
| 688 } | 712 } |
| 689 | 713 |
| 690 | 714 |
| 691 Object* StubCache::ComputeCallMiss(int argc) { | 715 Object* StubCache::ComputeCallMiss(int argc, Code::Kind kind) { |
| 692 Code::Flags flags = | 716 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs |
| 693 Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, MEGAMORPHIC, NORMAL, argc); | 717 // and monomorphic stubs are not mixed up together in the stub cache. |
| 718 Code::Flags flags = Code::ComputeFlags( |
| 719 kind, NOT_IN_LOOP, MONOMORPHIC_PROTOTYPE_FAILURE, NORMAL, argc); |
| 694 Object* probe = ProbeCache(flags); | 720 Object* probe = ProbeCache(flags); |
| 695 if (!probe->IsUndefined()) return probe; | 721 if (!probe->IsUndefined()) return probe; |
| 696 StubCompiler compiler; | 722 StubCompiler compiler; |
| 697 return FillCache(compiler.CompileCallMiss(flags)); | 723 return FillCache(compiler.CompileCallMiss(flags)); |
| 698 } | 724 } |
| 699 | 725 |
| 700 | 726 |
| 701 #ifdef ENABLE_DEBUGGER_SUPPORT | 727 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 702 Object* StubCache::ComputeCallDebugBreak(int argc) { | 728 Object* StubCache::ComputeCallDebugBreak(int argc, Code::Kind kind) { |
| 703 Code::Flags flags = | 729 Code::Flags flags = |
| 704 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc); | 730 Code::ComputeFlags(kind, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc); |
| 705 Object* probe = ProbeCache(flags); | 731 Object* probe = ProbeCache(flags); |
| 706 if (!probe->IsUndefined()) return probe; | 732 if (!probe->IsUndefined()) return probe; |
| 707 StubCompiler compiler; | 733 StubCompiler compiler; |
| 708 return FillCache(compiler.CompileCallDebugBreak(flags)); | 734 return FillCache(compiler.CompileCallDebugBreak(flags)); |
| 709 } | 735 } |
| 710 | 736 |
| 711 | 737 |
| 712 Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) { | 738 Object* StubCache::ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) { |
| 713 Code::Flags flags = | 739 Code::Flags flags = |
| 714 Code::ComputeFlags(Code::CALL_IC, | 740 Code::ComputeFlags(kind, |
| 715 NOT_IN_LOOP, | 741 NOT_IN_LOOP, |
| 716 DEBUG_PREPARE_STEP_IN, | 742 DEBUG_PREPARE_STEP_IN, |
| 717 NORMAL, | 743 NORMAL, |
| 718 argc); | 744 argc); |
| 719 Object* probe = ProbeCache(flags); | 745 Object* probe = ProbeCache(flags); |
| 720 if (!probe->IsUndefined()) return probe; | 746 if (!probe->IsUndefined()) return probe; |
| 721 StubCompiler compiler; | 747 StubCompiler compiler; |
| 722 return FillCache(compiler.CompileCallDebugPrepareStepIn(flags)); | 748 return FillCache(compiler.CompileCallDebugPrepareStepIn(flags)); |
| 723 } | 749 } |
| 724 #endif | 750 #endif |
| (...skipping 26 matching lines...) Expand all Loading... |
| 751 secondary_[j].value = Builtins::builtin(Builtins::Illegal); | 777 secondary_[j].value = Builtins::builtin(Builtins::Illegal); |
| 752 } | 778 } |
| 753 } | 779 } |
| 754 | 780 |
| 755 | 781 |
| 756 // ------------------------------------------------------------------------ | 782 // ------------------------------------------------------------------------ |
| 757 // StubCompiler implementation. | 783 // StubCompiler implementation. |
| 758 | 784 |
| 759 | 785 |
| 760 // Support function for computing call IC miss stubs. | 786 // Support function for computing call IC miss stubs. |
| 761 Handle<Code> ComputeCallMiss(int argc) { | 787 Handle<Code> ComputeCallMiss(int argc, Code::Kind kind) { |
| 762 CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc), Code); | 788 CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc, kind), Code); |
| 763 } | 789 } |
| 764 | 790 |
| 765 | 791 |
| 766 | 792 |
| 767 Object* LoadCallbackProperty(Arguments args) { | 793 Object* LoadCallbackProperty(Arguments args) { |
| 768 ASSERT(args[0]->IsJSObject()); | 794 ASSERT(args[0]->IsJSObject()); |
| 769 ASSERT(args[1]->IsJSObject()); | 795 ASSERT(args[1]->IsJSObject()); |
| 770 AccessorInfo* callback = AccessorInfo::cast(args[2]); | 796 AccessorInfo* callback = AccessorInfo::cast(args[2]); |
| 771 Address getter_address = v8::ToCData<Address>(callback->getter()); | 797 Address getter_address = v8::ToCData<Address>(callback->getter()); |
| 772 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address); | 798 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 Object* KeyedLoadPropertyWithInterceptor(Arguments args) { | 985 Object* KeyedLoadPropertyWithInterceptor(Arguments args) { |
| 960 JSObject* receiver = JSObject::cast(args[0]); | 986 JSObject* receiver = JSObject::cast(args[0]); |
| 961 uint32_t index = Smi::cast(args[1])->value(); | 987 uint32_t index = Smi::cast(args[1])->value(); |
| 962 return receiver->GetElementWithInterceptor(receiver, index); | 988 return receiver->GetElementWithInterceptor(receiver, index); |
| 963 } | 989 } |
| 964 | 990 |
| 965 | 991 |
| 966 Object* StubCompiler::CompileCallInitialize(Code::Flags flags) { | 992 Object* StubCompiler::CompileCallInitialize(Code::Flags flags) { |
| 967 HandleScope scope; | 993 HandleScope scope; |
| 968 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 994 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 969 CallIC::GenerateInitialize(masm(), argc); | 995 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 996 if (kind == Code::CALL_IC) { |
| 997 CallIC::GenerateInitialize(masm(), argc); |
| 998 } else { |
| 999 KeyedCallIC::GenerateInitialize(masm(), argc); |
| 1000 } |
| 970 Object* result = GetCodeWithFlags(flags, "CompileCallInitialize"); | 1001 Object* result = GetCodeWithFlags(flags, "CompileCallInitialize"); |
| 971 if (!result->IsFailure()) { | 1002 if (!result->IsFailure()) { |
| 972 Counters::call_initialize_stubs.Increment(); | 1003 Counters::call_initialize_stubs.Increment(); |
| 973 Code* code = Code::cast(result); | 1004 Code* code = Code::cast(result); |
| 974 USE(code); | 1005 USE(code); |
| 975 PROFILE(CodeCreateEvent(Logger::CALL_INITIALIZE_TAG, | 1006 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG), |
| 976 code, code->arguments_count())); | 1007 code, code->arguments_count())); |
| 977 } | 1008 } |
| 978 return result; | 1009 return result; |
| 979 } | 1010 } |
| 980 | 1011 |
| 981 | 1012 |
| 982 Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { | 1013 Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { |
| 983 HandleScope scope; | 1014 HandleScope scope; |
| 984 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1015 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 985 // The code of the PreMonomorphic stub is the same as the code | 1016 // The code of the PreMonomorphic stub is the same as the code |
| 986 // of the Initialized stub. They just differ on the code object flags. | 1017 // of the Initialized stub. They just differ on the code object flags. |
| 987 CallIC::GenerateInitialize(masm(), argc); | 1018 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1019 if (kind == Code::CALL_IC) { |
| 1020 CallIC::GenerateInitialize(masm(), argc); |
| 1021 } else { |
| 1022 KeyedCallIC::GenerateInitialize(masm(), argc); |
| 1023 } |
| 988 Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); | 1024 Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); |
| 989 if (!result->IsFailure()) { | 1025 if (!result->IsFailure()) { |
| 990 Counters::call_premonomorphic_stubs.Increment(); | 1026 Counters::call_premonomorphic_stubs.Increment(); |
| 991 Code* code = Code::cast(result); | 1027 Code* code = Code::cast(result); |
| 992 USE(code); | 1028 USE(code); |
| 993 PROFILE(CodeCreateEvent(Logger::CALL_PRE_MONOMORPHIC_TAG, | 1029 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG), |
| 994 code, code->arguments_count())); | 1030 code, code->arguments_count())); |
| 995 } | 1031 } |
| 996 return result; | 1032 return result; |
| 997 } | 1033 } |
| 998 | 1034 |
| 999 | 1035 |
| 1000 Object* StubCompiler::CompileCallNormal(Code::Flags flags) { | 1036 Object* StubCompiler::CompileCallNormal(Code::Flags flags) { |
| 1001 HandleScope scope; | 1037 HandleScope scope; |
| 1002 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1038 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1003 CallIC::GenerateNormal(masm(), argc); | 1039 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1040 if (kind == Code::CALL_IC) { |
| 1041 CallIC::GenerateNormal(masm(), argc); |
| 1042 } else { |
| 1043 KeyedCallIC::GenerateNormal(masm(), argc); |
| 1044 } |
| 1004 Object* result = GetCodeWithFlags(flags, "CompileCallNormal"); | 1045 Object* result = GetCodeWithFlags(flags, "CompileCallNormal"); |
| 1005 if (!result->IsFailure()) { | 1046 if (!result->IsFailure()) { |
| 1006 Counters::call_normal_stubs.Increment(); | 1047 Counters::call_normal_stubs.Increment(); |
| 1007 Code* code = Code::cast(result); | 1048 Code* code = Code::cast(result); |
| 1008 USE(code); | 1049 USE(code); |
| 1009 PROFILE(CodeCreateEvent(Logger::CALL_NORMAL_TAG, | 1050 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), |
| 1010 code, code->arguments_count())); | 1051 code, code->arguments_count())); |
| 1011 } | 1052 } |
| 1012 return result; | 1053 return result; |
| 1013 } | 1054 } |
| 1014 | 1055 |
| 1015 | 1056 |
| 1016 Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) { | 1057 Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) { |
| 1017 HandleScope scope; | 1058 HandleScope scope; |
| 1018 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1059 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1019 CallIC::GenerateMegamorphic(masm(), argc); | 1060 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1061 if (kind == Code::CALL_IC) { |
| 1062 CallIC::GenerateMegamorphic(masm(), argc); |
| 1063 } else { |
| 1064 KeyedCallIC::GenerateMegamorphic(masm(), argc); |
| 1065 } |
| 1066 |
| 1020 Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic"); | 1067 Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic"); |
| 1021 if (!result->IsFailure()) { | 1068 if (!result->IsFailure()) { |
| 1022 Counters::call_megamorphic_stubs.Increment(); | 1069 Counters::call_megamorphic_stubs.Increment(); |
| 1023 Code* code = Code::cast(result); | 1070 Code* code = Code::cast(result); |
| 1024 USE(code); | 1071 USE(code); |
| 1025 PROFILE(CodeCreateEvent(Logger::CALL_MEGAMORPHIC_TAG, | 1072 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG), |
| 1026 code, code->arguments_count())); | 1073 code, code->arguments_count())); |
| 1027 } | 1074 } |
| 1028 return result; | 1075 return result; |
| 1029 } | 1076 } |
| 1030 | 1077 |
| 1031 | 1078 |
| 1032 Object* StubCompiler::CompileCallMiss(Code::Flags flags) { | 1079 Object* StubCompiler::CompileCallMiss(Code::Flags flags) { |
| 1033 HandleScope scope; | 1080 HandleScope scope; |
| 1034 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1081 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1035 CallIC::GenerateMiss(masm(), argc); | 1082 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1083 if (kind == Code::CALL_IC) { |
| 1084 CallIC::GenerateMiss(masm(), argc); |
| 1085 } else { |
| 1086 KeyedCallIC::GenerateMiss(masm(), argc); |
| 1087 } |
| 1036 Object* result = GetCodeWithFlags(flags, "CompileCallMiss"); | 1088 Object* result = GetCodeWithFlags(flags, "CompileCallMiss"); |
| 1037 if (!result->IsFailure()) { | 1089 if (!result->IsFailure()) { |
| 1038 Counters::call_megamorphic_stubs.Increment(); | 1090 Counters::call_megamorphic_stubs.Increment(); |
| 1039 Code* code = Code::cast(result); | 1091 Code* code = Code::cast(result); |
| 1040 USE(code); | 1092 USE(code); |
| 1041 PROFILE(CodeCreateEvent(Logger::CALL_MISS_TAG, | 1093 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), |
| 1042 code, code->arguments_count())); | 1094 code, code->arguments_count())); |
| 1043 } | 1095 } |
| 1044 return result; | 1096 return result; |
| 1045 } | 1097 } |
| 1046 | 1098 |
| 1047 | 1099 |
| 1048 #ifdef ENABLE_DEBUGGER_SUPPORT | 1100 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 1049 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) { | 1101 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) { |
| 1050 HandleScope scope; | 1102 HandleScope scope; |
| 1051 Debug::GenerateCallICDebugBreak(masm()); | 1103 Debug::GenerateCallICDebugBreak(masm()); |
| 1052 Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak"); | 1104 Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak"); |
| 1053 if (!result->IsFailure()) { | 1105 if (!result->IsFailure()) { |
| 1054 Code* code = Code::cast(result); | 1106 Code* code = Code::cast(result); |
| 1055 USE(code); | 1107 USE(code); |
| 1056 PROFILE(CodeCreateEvent(Logger::CALL_DEBUG_BREAK_TAG, | 1108 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1109 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG), |
| 1057 code, code->arguments_count())); | 1110 code, code->arguments_count())); |
| 1058 } | 1111 } |
| 1059 return result; | 1112 return result; |
| 1060 } | 1113 } |
| 1061 | 1114 |
| 1062 | 1115 |
| 1063 Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { | 1116 Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { |
| 1064 HandleScope scope; | 1117 HandleScope scope; |
| 1065 // Use the same code for the the step in preparations as we do for | 1118 // Use the same code for the the step in preparations as we do for |
| 1066 // the miss case. | 1119 // the miss case. |
| 1067 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1120 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1068 CallIC::GenerateMiss(masm(), argc); | 1121 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1122 if (kind == Code::CALL_IC) { |
| 1123 CallIC::GenerateMiss(masm(), argc); |
| 1124 } else { |
| 1125 KeyedCallIC::GenerateMiss(masm(), argc); |
| 1126 } |
| 1069 Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); | 1127 Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); |
| 1070 if (!result->IsFailure()) { | 1128 if (!result->IsFailure()) { |
| 1071 Code* code = Code::cast(result); | 1129 Code* code = Code::cast(result); |
| 1072 USE(code); | 1130 USE(code); |
| 1073 PROFILE(CodeCreateEvent(Logger::CALL_DEBUG_PREPARE_STEP_IN_TAG, | 1131 PROFILE(CodeCreateEvent( |
| 1074 code, code->arguments_count())); | 1132 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG), |
| 1133 code, |
| 1134 code->arguments_count())); |
| 1075 } | 1135 } |
| 1076 return result; | 1136 return result; |
| 1077 } | 1137 } |
| 1078 #endif | 1138 #endif |
| 1079 | 1139 |
| 1140 #undef CALL_LOGGER_TAG |
| 1080 | 1141 |
| 1081 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) { | 1142 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) { |
| 1082 // Check for allocation failures during stub compilation. | 1143 // Check for allocation failures during stub compilation. |
| 1083 if (failure_->IsFailure()) return failure_; | 1144 if (failure_->IsFailure()) return failure_; |
| 1084 | 1145 |
| 1085 // Create code object in the heap. | 1146 // Create code object in the heap. |
| 1086 CodeDesc desc; | 1147 CodeDesc desc; |
| 1087 masm_.GetCode(&desc); | 1148 masm_.GetCode(&desc); |
| 1088 Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject()); | 1149 Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject()); |
| 1089 #ifdef ENABLE_DISASSEMBLER | 1150 #ifdef ENABLE_DISASSEMBLER |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1160 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | 1221 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) |
| 1161 #undef CALL_GENERATOR_CASE | 1222 #undef CALL_GENERATOR_CASE |
| 1162 } | 1223 } |
| 1163 UNREACHABLE(); | 1224 UNREACHABLE(); |
| 1164 return Heap::undefined_value(); | 1225 return Heap::undefined_value(); |
| 1165 } | 1226 } |
| 1166 | 1227 |
| 1167 | 1228 |
| 1168 Object* CallStubCompiler::GetCode(PropertyType type, String* name) { | 1229 Object* CallStubCompiler::GetCode(PropertyType type, String* name) { |
| 1169 int argc = arguments_.immediate(); | 1230 int argc = arguments_.immediate(); |
| 1170 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 1231 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, |
| 1171 type, | 1232 type, |
| 1172 in_loop_, | 1233 in_loop_, |
| 1173 argc); | 1234 argc); |
| 1174 return GetCodeWithFlags(flags, name); | 1235 return GetCodeWithFlags(flags, name); |
| 1175 } | 1236 } |
| 1176 | 1237 |
| 1177 | 1238 |
| 1178 Object* CallStubCompiler::GetCode(JSFunction* function) { | 1239 Object* CallStubCompiler::GetCode(JSFunction* function) { |
| 1179 String* function_name = NULL; | 1240 String* function_name = NULL; |
| 1180 if (function->shared()->name()->IsString()) { | 1241 if (function->shared()->name()->IsString()) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1257 expected_receiver_type_ = | 1318 expected_receiver_type_ = |
| 1258 FunctionTemplateInfo::cast(signature->receiver()); | 1319 FunctionTemplateInfo::cast(signature->receiver()); |
| 1259 } | 1320 } |
| 1260 } | 1321 } |
| 1261 | 1322 |
| 1262 is_simple_api_call_ = true; | 1323 is_simple_api_call_ = true; |
| 1263 } | 1324 } |
| 1264 | 1325 |
| 1265 | 1326 |
| 1266 } } // namespace v8::internal | 1327 } } // namespace v8::internal |
| OLD | NEW |