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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 const int argc = this->target()->arguments_count(); | 380 const int argc = this->target()->arguments_count(); |
381 StackFrameLocator locator; | 381 StackFrameLocator locator; |
382 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 382 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
383 int index = frame->ComputeExpressionsCount() - (argc + 1); | 383 int index = frame->ComputeExpressionsCount() - (argc + 1); |
384 frame->SetExpression(index, *target); | 384 frame->SetExpression(index, *target); |
385 } | 385 } |
386 | 386 |
387 return *delegate; | 387 return *delegate; |
388 } | 388 } |
389 | 389 |
| 390 |
390 void CallICBase::ReceiverToObject(Handle<Object> object) { | 391 void CallICBase::ReceiverToObject(Handle<Object> object) { |
391 HandleScope scope; | 392 HandleScope scope; |
392 Handle<Object> receiver(object); | 393 Handle<Object> receiver(object); |
393 | 394 |
394 // Change the receiver to the result of calling ToObject on it. | 395 // Change the receiver to the result of calling ToObject on it. |
395 const int argc = this->target()->arguments_count(); | 396 const int argc = this->target()->arguments_count(); |
396 StackFrameLocator locator; | 397 StackFrameLocator locator; |
397 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 398 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
398 int index = frame->ComputeExpressionsCount() - (argc + 1); | 399 int index = frame->ComputeExpressionsCount() - (argc + 1); |
399 frame->SetExpression(index, *Factory::ToObject(object)); | 400 frame->SetExpression(index, *Factory::ToObject(object)); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 // If we're unable to compute the stub (not enough memory left), we | 582 // If we're unable to compute the stub (not enough memory left), we |
582 // simply avoid updating the caches. | 583 // simply avoid updating the caches. |
583 if (code == NULL || code->IsFailure()) return; | 584 if (code == NULL || code->IsFailure()) return; |
584 | 585 |
585 // Patch the call site depending on the state of the cache. | 586 // Patch the call site depending on the state of the cache. |
586 if (state == UNINITIALIZED || | 587 if (state == UNINITIALIZED || |
587 state == PREMONOMORPHIC || | 588 state == PREMONOMORPHIC || |
588 state == MONOMORPHIC || | 589 state == MONOMORPHIC || |
589 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 590 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
590 set_target(Code::cast(code)); | 591 set_target(Code::cast(code)); |
| 592 } else if (state == MEGAMORPHIC) { |
| 593 // Update the stub cache. |
| 594 StubCache::Set(*name, GetCodeCacheMapForObject(*object), Code::cast(code)); |
591 } | 595 } |
592 | 596 |
593 #ifdef DEBUG | 597 #ifdef DEBUG |
594 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 598 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
595 name, state, target(), in_loop ? " (in-loop)" : ""); | 599 name, state, target(), in_loop ? " (in-loop)" : ""); |
596 #endif | 600 #endif |
597 } | 601 } |
598 | 602 |
599 | 603 |
600 Object* KeyedCallIC::LoadFunction(State state, | 604 Object* KeyedCallIC::LoadFunction(State state, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 #endif | 661 #endif |
658 Map* map = HeapObject::cast(*object)->map(); | 662 Map* map = HeapObject::cast(*object)->map(); |
659 if (object->IsString()) { | 663 if (object->IsString()) { |
660 const int offset = String::kLengthOffset; | 664 const int offset = String::kLengthOffset; |
661 PatchInlinedLoad(address(), map, offset); | 665 PatchInlinedLoad(address(), map, offset); |
662 } | 666 } |
663 | 667 |
664 Code* target = NULL; | 668 Code* target = NULL; |
665 target = Builtins::builtin(Builtins::LoadIC_StringLength); | 669 target = Builtins::builtin(Builtins::LoadIC_StringLength); |
666 set_target(target); | 670 set_target(target); |
667 StubCache::Set(*name, map, target); | |
668 return Smi::FromInt(String::cast(*object)->length()); | 671 return Smi::FromInt(String::cast(*object)->length()); |
669 } | 672 } |
670 | 673 |
671 // Use specialized code for getting the length of arrays. | 674 // Use specialized code for getting the length of arrays. |
672 if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { | 675 if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { |
673 #ifdef DEBUG | 676 #ifdef DEBUG |
674 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); | 677 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); |
675 #endif | 678 #endif |
676 Map* map = HeapObject::cast(*object)->map(); | 679 Map* map = HeapObject::cast(*object)->map(); |
677 const int offset = JSArray::kLengthOffset; | 680 const int offset = JSArray::kLengthOffset; |
678 PatchInlinedLoad(address(), map, offset); | 681 PatchInlinedLoad(address(), map, offset); |
679 | 682 |
680 Code* target = Builtins::builtin(Builtins::LoadIC_ArrayLength); | 683 Code* target = Builtins::builtin(Builtins::LoadIC_ArrayLength); |
681 set_target(target); | 684 set_target(target); |
682 StubCache::Set(*name, map, target); | |
683 return JSArray::cast(*object)->length(); | 685 return JSArray::cast(*object)->length(); |
684 } | 686 } |
685 | 687 |
686 // Use specialized code for getting prototype of functions. | 688 // Use specialized code for getting prototype of functions. |
687 if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && | 689 if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && |
688 JSFunction::cast(*object)->should_have_prototype()) { | 690 JSFunction::cast(*object)->should_have_prototype()) { |
689 #ifdef DEBUG | 691 #ifdef DEBUG |
690 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 692 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); |
691 #endif | 693 #endif |
692 Code* target = Builtins::builtin(Builtins::LoadIC_FunctionPrototype); | 694 Code* target = Builtins::builtin(Builtins::LoadIC_FunctionPrototype); |
693 set_target(target); | 695 set_target(target); |
694 StubCache::Set(*name, HeapObject::cast(*object)->map(), target); | |
695 return Accessors::FunctionGetPrototype(*object, 0); | 696 return Accessors::FunctionGetPrototype(*object, 0); |
696 } | 697 } |
697 } | 698 } |
698 | 699 |
699 // Check if the name is trivially convertible to an index and get | 700 // Check if the name is trivially convertible to an index and get |
700 // the element if so. | 701 // the element if so. |
701 uint32_t index; | 702 uint32_t index; |
702 if (name->AsArrayIndex(&index)) return object->GetElement(index); | 703 if (name->AsArrayIndex(&index)) return object->GetElement(index); |
703 | 704 |
704 // Named lookup in the object. | 705 // Named lookup in the object. |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 // If we're unable to compute the stub (not enough memory left), we | 841 // If we're unable to compute the stub (not enough memory left), we |
841 // simply avoid updating the caches. | 842 // simply avoid updating the caches. |
842 if (code == NULL || code->IsFailure()) return; | 843 if (code == NULL || code->IsFailure()) return; |
843 | 844 |
844 // Patch the call site depending on the state of the cache. | 845 // Patch the call site depending on the state of the cache. |
845 if (state == UNINITIALIZED || state == PREMONOMORPHIC || | 846 if (state == UNINITIALIZED || state == PREMONOMORPHIC || |
846 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 847 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
847 set_target(Code::cast(code)); | 848 set_target(Code::cast(code)); |
848 } else if (state == MONOMORPHIC) { | 849 } else if (state == MONOMORPHIC) { |
849 set_target(megamorphic_stub()); | 850 set_target(megamorphic_stub()); |
| 851 } else if (state == MEGAMORPHIC) { |
| 852 // Update the stub cache. |
| 853 StubCache::Set(*name, GetCodeCacheMapForObject(*object), Code::cast(code)); |
850 } | 854 } |
851 | 855 |
852 #ifdef DEBUG | 856 #ifdef DEBUG |
853 TraceIC("LoadIC", name, state, target()); | 857 TraceIC("LoadIC", name, state, target()); |
854 #endif | 858 #endif |
855 } | 859 } |
856 | 860 |
857 | 861 |
858 Object* KeyedLoadIC::Load(State state, | 862 Object* KeyedLoadIC::Load(State state, |
859 Handle<Object> object, | 863 Handle<Object> object, |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 | 1107 |
1104 // Check if the given name is an array index. | 1108 // Check if the given name is an array index. |
1105 uint32_t index; | 1109 uint32_t index; |
1106 if (name->AsArrayIndex(&index)) { | 1110 if (name->AsArrayIndex(&index)) { |
1107 HandleScope scope; | 1111 HandleScope scope; |
1108 Handle<Object> result = SetElement(receiver, index, value); | 1112 Handle<Object> result = SetElement(receiver, index, value); |
1109 if (result.is_null()) return Failure::Exception(); | 1113 if (result.is_null()) return Failure::Exception(); |
1110 return *value; | 1114 return *value; |
1111 } | 1115 } |
1112 | 1116 |
1113 | |
1114 // Use specialized code for setting the length of arrays. | 1117 // Use specialized code for setting the length of arrays. |
1115 if (receiver->IsJSArray() | 1118 if (receiver->IsJSArray() |
1116 && name->Equals(Heap::length_symbol()) | 1119 && name->Equals(Heap::length_symbol()) |
1117 && receiver->AllowsSetElementsLength()) { | 1120 && receiver->AllowsSetElementsLength()) { |
1118 #ifdef DEBUG | 1121 #ifdef DEBUG |
1119 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); | 1122 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); |
1120 #endif | 1123 #endif |
1121 Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength); | 1124 Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength); |
1122 set_target(target); | 1125 set_target(target); |
1123 StubCache::Set(*name, HeapObject::cast(*object)->map(), target); | |
1124 return receiver->SetProperty(*name, *value, NONE); | 1126 return receiver->SetProperty(*name, *value, NONE); |
1125 } | 1127 } |
1126 | 1128 |
1127 // Lookup the property locally in the receiver. | 1129 // Lookup the property locally in the receiver. |
1128 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { | 1130 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { |
1129 LookupResult lookup; | 1131 LookupResult lookup; |
1130 if (LookupForWrite(*receiver, *name, &lookup)) { | 1132 if (LookupForWrite(*receiver, *name, &lookup)) { |
1131 UpdateCaches(&lookup, state, receiver, name, value); | 1133 UpdateCaches(&lookup, state, receiver, name, value); |
1132 } | 1134 } |
1133 } | 1135 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1201 } | 1203 } |
1202 | 1204 |
1203 // If we're unable to compute the stub (not enough memory left), we | 1205 // If we're unable to compute the stub (not enough memory left), we |
1204 // simply avoid updating the caches. | 1206 // simply avoid updating the caches. |
1205 if (code == NULL || code->IsFailure()) return; | 1207 if (code == NULL || code->IsFailure()) return; |
1206 | 1208 |
1207 // Patch the call site depending on the state of the cache. | 1209 // Patch the call site depending on the state of the cache. |
1208 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 1210 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
1209 set_target(Code::cast(code)); | 1211 set_target(Code::cast(code)); |
1210 } else if (state == MONOMORPHIC) { | 1212 } else if (state == MONOMORPHIC) { |
1211 // Only move to mega morphic if the target changes. | 1213 // Only move to megamorphic if the target changes. |
1212 if (target() != Code::cast(code)) set_target(megamorphic_stub()); | 1214 if (target() != Code::cast(code)) set_target(megamorphic_stub()); |
| 1215 } else if (state == MEGAMORPHIC) { |
| 1216 // Update the stub cache. |
| 1217 StubCache::Set(*name, receiver->map(), Code::cast(code)); |
1213 } | 1218 } |
1214 | 1219 |
1215 #ifdef DEBUG | 1220 #ifdef DEBUG |
1216 TraceIC("StoreIC", name, state, target()); | 1221 TraceIC("StoreIC", name, state, target()); |
1217 #endif | 1222 #endif |
1218 } | 1223 } |
1219 | 1224 |
1220 | 1225 |
1221 Object* KeyedStoreIC::Store(State state, | 1226 Object* KeyedStoreIC::Store(State state, |
1222 Handle<Object> object, | 1227 Handle<Object> object, |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1590 #undef ADDR | 1595 #undef ADDR |
1591 }; | 1596 }; |
1592 | 1597 |
1593 | 1598 |
1594 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1599 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
1595 return IC_utilities[id]; | 1600 return IC_utilities[id]; |
1596 } | 1601 } |
1597 | 1602 |
1598 | 1603 |
1599 } } // namespace v8::internal | 1604 } } // namespace v8::internal |
OLD | NEW |