| 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 |