| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 case Code::COMPARE_IC: | 287 case Code::COMPARE_IC: |
| 288 // Clearing these is tricky and does not | 288 // Clearing these is tricky and does not |
| 289 // make any performance difference. | 289 // make any performance difference. |
| 290 return; | 290 return; |
| 291 default: UNREACHABLE(); | 291 default: UNREACHABLE(); |
| 292 } | 292 } |
| 293 } | 293 } |
| 294 | 294 |
| 295 | 295 |
| 296 void CallICBase::Clear(Address address, Code* target) { | 296 void CallICBase::Clear(Address address, Code* target) { |
| 297 bool contextual = CallICBase::Contextual::decode(target->extra_ic_state()); |
| 297 State state = target->ic_state(); | 298 State state = target->ic_state(); |
| 298 if (state == UNINITIALIZED) return; | 299 if (state == UNINITIALIZED) return; |
| 299 Code* code = | 300 Code* code = |
| 300 Isolate::Current()->stub_cache()->FindCallInitialize( | 301 Isolate::Current()->stub_cache()->FindCallInitialize( |
| 301 target->arguments_count(), | 302 target->arguments_count(), |
| 302 target->ic_in_loop(), | 303 target->ic_in_loop(), |
| 304 contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET, |
| 303 target->kind()); | 305 target->kind()); |
| 304 SetTargetAtAddress(address, code); | 306 SetTargetAtAddress(address, code); |
| 305 } | 307 } |
| 306 | 308 |
| 307 | 309 |
| 308 void KeyedLoadIC::Clear(Address address, Code* target) { | 310 void KeyedLoadIC::Clear(Address address, Code* target) { |
| 309 if (target->ic_state() == UNINITIALIZED) return; | 311 if (target->ic_state() == UNINITIALIZED) return; |
| 310 // Make sure to also clear the map used in inline fast cases. If we | 312 // Make sure to also clear the map used in inline fast cases. If we |
| 311 // do not clear these maps, cached code can keep objects alive | 313 // do not clear these maps, cached code can keep objects alive |
| 312 // through the embedded maps. | 314 // through the embedded maps. |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 argc * kPointerSize)); | 545 argc * kPointerSize)); |
| 544 switch (function->shared()->builtin_function_id()) { | 546 switch (function->shared()->builtin_function_id()) { |
| 545 case kStringCharCodeAt: | 547 case kStringCharCodeAt: |
| 546 case kStringCharAt: | 548 case kStringCharAt: |
| 547 if (object->IsString()) { | 549 if (object->IsString()) { |
| 548 String* string = String::cast(*object); | 550 String* string = String::cast(*object); |
| 549 // Check there's the right string value or wrapper in the receiver slot. | 551 // Check there's the right string value or wrapper in the receiver slot. |
| 550 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); | 552 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); |
| 551 // If we're in the default (fastest) state and the index is | 553 // If we're in the default (fastest) state and the index is |
| 552 // out of bounds, update the state to record this fact. | 554 // out of bounds, update the state to record this fact. |
| 553 if (*extra_ic_state == DEFAULT_STRING_STUB && | 555 if (StringStubState::decode(*extra_ic_state) == DEFAULT_STRING_STUB && |
| 554 argc >= 1 && args[1]->IsNumber()) { | 556 argc >= 1 && args[1]->IsNumber()) { |
| 555 double index; | 557 double index; |
| 556 if (args[1]->IsSmi()) { | 558 if (args[1]->IsSmi()) { |
| 557 index = Smi::cast(args[1])->value(); | 559 index = Smi::cast(args[1])->value(); |
| 558 } else { | 560 } else { |
| 559 ASSERT(args[1]->IsHeapNumber()); | 561 ASSERT(args[1]->IsHeapNumber()); |
| 560 index = DoubleToInteger(HeapNumber::cast(args[1])->value()); | 562 index = DoubleToInteger(HeapNumber::cast(args[1])->value()); |
| 561 } | 563 } |
| 562 if (index < 0 || index >= string->length()) { | 564 if (index < 0 || index >= string->length()) { |
| 563 *extra_ic_state = STRING_INDEX_OUT_OF_BOUNDS; | 565 *extra_ic_state = |
| 566 StringStubState::update(*extra_ic_state, |
| 567 STRING_INDEX_OUT_OF_BOUNDS); |
| 564 return true; | 568 return true; |
| 565 } | 569 } |
| 566 } | 570 } |
| 567 } | 571 } |
| 568 break; | 572 break; |
| 569 default: | 573 default: |
| 570 return false; | 574 return false; |
| 571 } | 575 } |
| 572 return false; | 576 return false; |
| 573 } | 577 } |
| 574 | 578 |
| 575 | 579 |
| 576 MaybeObject* CallICBase::ComputeMonomorphicStub( | 580 MaybeObject* CallICBase::ComputeMonomorphicStub( |
| 577 LookupResult* lookup, | 581 LookupResult* lookup, |
| 578 State state, | 582 State state, |
| 579 Code::ExtraICState extra_ic_state, | 583 Code::ExtraICState extra_ic_state, |
| 580 Handle<Object> object, | 584 Handle<Object> object, |
| 581 Handle<String> name) { | 585 Handle<String> name) { |
| 582 int argc = target()->arguments_count(); | 586 int argc = target()->arguments_count(); |
| 583 InLoopFlag in_loop = target()->ic_in_loop(); | 587 InLoopFlag in_loop = target()->ic_in_loop(); |
| 584 MaybeObject* maybe_code = NULL; | 588 MaybeObject* maybe_code = NULL; |
| 585 switch (lookup->type()) { | 589 switch (lookup->type()) { |
| 586 case FIELD: { | 590 case FIELD: { |
| 587 int index = lookup->GetFieldIndex(); | 591 int index = lookup->GetFieldIndex(); |
| 588 maybe_code = isolate()->stub_cache()->ComputeCallField(argc, | 592 maybe_code = isolate()->stub_cache()->ComputeCallField(argc, |
| 589 in_loop, | 593 in_loop, |
| 590 kind_, | 594 kind_, |
| 595 extra_ic_state, |
| 591 *name, | 596 *name, |
| 592 *object, | 597 *object, |
| 593 lookup->holder(), | 598 lookup->holder(), |
| 594 index); | 599 index); |
| 595 break; | 600 break; |
| 596 } | 601 } |
| 597 case CONSTANT_FUNCTION: { | 602 case CONSTANT_FUNCTION: { |
| 598 // Get the constant function and compute the code stub for this | 603 // Get the constant function and compute the code stub for this |
| 599 // call; used for rewriting to monomorphic state and making sure | 604 // call; used for rewriting to monomorphic state and making sure |
| 600 // that the code stub is in the stub cache. | 605 // that the code stub is in the stub cache. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 616 | 621 |
| 617 if (lookup->holder()->IsGlobalObject()) { | 622 if (lookup->holder()->IsGlobalObject()) { |
| 618 GlobalObject* global = GlobalObject::cast(lookup->holder()); | 623 GlobalObject* global = GlobalObject::cast(lookup->holder()); |
| 619 JSGlobalPropertyCell* cell = | 624 JSGlobalPropertyCell* cell = |
| 620 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 625 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); |
| 621 if (!cell->value()->IsJSFunction()) return NULL; | 626 if (!cell->value()->IsJSFunction()) return NULL; |
| 622 JSFunction* function = JSFunction::cast(cell->value()); | 627 JSFunction* function = JSFunction::cast(cell->value()); |
| 623 maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, | 628 maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, |
| 624 in_loop, | 629 in_loop, |
| 625 kind_, | 630 kind_, |
| 631 extra_ic_state, |
| 626 *name, | 632 *name, |
| 627 *receiver, | 633 *receiver, |
| 628 global, | 634 global, |
| 629 cell, | 635 cell, |
| 630 function); | 636 function); |
| 631 } else { | 637 } else { |
| 632 // There is only one shared stub for calling normalized | 638 // There is only one shared stub for calling normalized |
| 633 // properties. It does not traverse the prototype chain, so the | 639 // properties. It does not traverse the prototype chain, so the |
| 634 // property must be found in the receiver for the stub to be | 640 // property must be found in the receiver for the stub to be |
| 635 // applicable. | 641 // applicable. |
| 636 if (lookup->holder() != *receiver) return NULL; | 642 if (lookup->holder() != *receiver) return NULL; |
| 637 maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, | 643 maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, |
| 638 in_loop, | 644 in_loop, |
| 639 kind_, | 645 kind_, |
| 646 extra_ic_state, |
| 640 *name, | 647 *name, |
| 641 *receiver); | 648 *receiver); |
| 642 } | 649 } |
| 643 break; | 650 break; |
| 644 } | 651 } |
| 645 case INTERCEPTOR: { | 652 case INTERCEPTOR: { |
| 646 ASSERT(HasInterceptorGetter(lookup->holder())); | 653 ASSERT(HasInterceptorGetter(lookup->holder())); |
| 647 maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( | 654 maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( |
| 648 argc, | 655 argc, |
| 649 kind_, | 656 kind_, |
| 657 extra_ic_state, |
| 650 *name, | 658 *name, |
| 651 *object, | 659 *object, |
| 652 lookup->holder()); | 660 lookup->holder()); |
| 653 break; | 661 break; |
| 654 } | 662 } |
| 655 default: | 663 default: |
| 656 maybe_code = NULL; | 664 maybe_code = NULL; |
| 657 break; | 665 break; |
| 658 } | 666 } |
| 659 return maybe_code; | 667 return maybe_code; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 678 | 686 |
| 679 // Compute the number of arguments. | 687 // Compute the number of arguments. |
| 680 int argc = target()->arguments_count(); | 688 int argc = target()->arguments_count(); |
| 681 InLoopFlag in_loop = target()->ic_in_loop(); | 689 InLoopFlag in_loop = target()->ic_in_loop(); |
| 682 MaybeObject* maybe_code = NULL; | 690 MaybeObject* maybe_code = NULL; |
| 683 bool had_proto_failure = false; | 691 bool had_proto_failure = false; |
| 684 if (state == UNINITIALIZED) { | 692 if (state == UNINITIALIZED) { |
| 685 // This is the first time we execute this inline cache. | 693 // This is the first time we execute this inline cache. |
| 686 // Set the target to the pre monomorphic stub to delay | 694 // Set the target to the pre monomorphic stub to delay |
| 687 // setting the monomorphic state. | 695 // setting the monomorphic state. |
| 688 maybe_code = isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, | 696 maybe_code = |
| 689 in_loop, | 697 isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, |
| 690 kind_); | 698 in_loop, |
| 699 kind_, |
| 700 extra_ic_state); |
| 691 } else if (state == MONOMORPHIC) { | 701 } else if (state == MONOMORPHIC) { |
| 692 if (kind_ == Code::CALL_IC && | 702 if (kind_ == Code::CALL_IC && |
| 693 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 703 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { |
| 694 maybe_code = ComputeMonomorphicStub(lookup, | 704 maybe_code = ComputeMonomorphicStub(lookup, |
| 695 state, | 705 state, |
| 696 extra_ic_state, | 706 extra_ic_state, |
| 697 object, | 707 object, |
| 698 name); | 708 name); |
| 699 } else if (kind_ == Code::CALL_IC && | 709 } else if (kind_ == Code::CALL_IC && |
| 700 TryRemoveInvalidPrototypeDependentStub(target(), | 710 TryRemoveInvalidPrototypeDependentStub(target(), |
| 701 *object, | 711 *object, |
| 702 *name)) { | 712 *name)) { |
| 703 had_proto_failure = true; | 713 had_proto_failure = true; |
| 704 maybe_code = ComputeMonomorphicStub(lookup, | 714 maybe_code = ComputeMonomorphicStub(lookup, |
| 705 state, | 715 state, |
| 706 extra_ic_state, | 716 extra_ic_state, |
| 707 object, | 717 object, |
| 708 name); | 718 name); |
| 709 } else { | 719 } else { |
| 710 maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(argc, | 720 maybe_code = |
| 711 in_loop, | 721 isolate()->stub_cache()->ComputeCallMegamorphic(argc, |
| 712 kind_); | 722 in_loop, |
| 723 kind_, |
| 724 extra_ic_state); |
| 713 } | 725 } |
| 714 } else { | 726 } else { |
| 715 maybe_code = ComputeMonomorphicStub(lookup, | 727 maybe_code = ComputeMonomorphicStub(lookup, |
| 716 state, | 728 state, |
| 717 extra_ic_state, | 729 extra_ic_state, |
| 718 object, | 730 object, |
| 719 name); | 731 name); |
| 720 } | 732 } |
| 721 | 733 |
| 722 // If we're unable to compute the stub (not enough memory left), we | 734 // If we're unable to compute the stub (not enough memory left), we |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 } | 772 } |
| 761 | 773 |
| 762 if (object->IsUndefined() || object->IsNull()) { | 774 if (object->IsUndefined() || object->IsNull()) { |
| 763 return TypeError("non_object_property_call", object, key); | 775 return TypeError("non_object_property_call", object, key); |
| 764 } | 776 } |
| 765 | 777 |
| 766 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { | 778 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { |
| 767 int argc = target()->arguments_count(); | 779 int argc = target()->arguments_count(); |
| 768 InLoopFlag in_loop = target()->ic_in_loop(); | 780 InLoopFlag in_loop = target()->ic_in_loop(); |
| 769 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( | 781 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 770 argc, in_loop, Code::KEYED_CALL_IC); | 782 argc, in_loop, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
| 771 Object* code; | 783 Object* code; |
| 772 if (maybe_code->ToObject(&code)) { | 784 if (maybe_code->ToObject(&code)) { |
| 773 set_target(Code::cast(code)); | 785 set_target(Code::cast(code)); |
| 774 #ifdef DEBUG | 786 #ifdef DEBUG |
| 775 TraceIC( | 787 TraceIC( |
| 776 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); | 788 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); |
| 777 #endif | 789 #endif |
| 778 } | 790 } |
| 779 } | 791 } |
| 780 | 792 |
| (...skipping 1409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2190 #undef ADDR | 2202 #undef ADDR |
| 2191 }; | 2203 }; |
| 2192 | 2204 |
| 2193 | 2205 |
| 2194 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2206 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2195 return IC_utilities[id]; | 2207 return IC_utilities[id]; |
| 2196 } | 2208 } |
| 2197 | 2209 |
| 2198 | 2210 |
| 2199 } } // namespace v8::internal | 2211 } } // namespace v8::internal |
| OLD | NEW |