| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 if (raw_frame->is_internal()) { | 82 if (raw_frame->is_internal()) { |
| 83 Code* apply_builtin = isolate()->builtins()->builtin( | 83 Code* apply_builtin = isolate()->builtins()->builtin( |
| 84 Builtins::kFunctionApply); | 84 Builtins::kFunctionApply); |
| 85 if (raw_frame->unchecked_code() == apply_builtin) { | 85 if (raw_frame->unchecked_code() == apply_builtin) { |
| 86 PrintF("apply from "); | 86 PrintF("apply from "); |
| 87 it.Advance(); | 87 it.Advance(); |
| 88 raw_frame = it.frame(); | 88 raw_frame = it.frame(); |
| 89 } | 89 } |
| 90 } | 90 } |
| 91 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 91 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
| 92 Code::ExtraICState extra_state = new_target->extra_ic_state(); | 92 ExtraICState extra_state = new_target->extra_ic_state(); |
| 93 const char* modifier = | 93 const char* modifier = |
| 94 GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(extra_state)); | 94 GetTransitionMarkModifier( |
| 95 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); |
| 95 PrintF(" (%c->%c%s)", | 96 PrintF(" (%c->%c%s)", |
| 96 TransitionMarkFromState(state()), | 97 TransitionMarkFromState(state()), |
| 97 TransitionMarkFromState(new_state), | 98 TransitionMarkFromState(new_state), |
| 98 modifier); | 99 modifier); |
| 99 name->Print(); | 100 name->Print(); |
| 100 PrintF("]\n"); | 101 PrintF("]\n"); |
| 101 } | 102 } |
| 102 } | 103 } |
| 103 | 104 |
| 104 #define TRACE_GENERIC_IC(isolate, type, reason) \ | 105 #define TRACE_GENERIC_IC(isolate, type, reason) \ |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 526 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
| 526 if (IsCleared(target)) return; | 527 if (IsCleared(target)) return; |
| 527 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); | 528 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); |
| 528 } | 529 } |
| 529 | 530 |
| 530 | 531 |
| 531 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { | 532 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { |
| 532 if (IsCleared(target)) return; | 533 if (IsCleared(target)) return; |
| 533 SetTargetAtAddress(address, | 534 SetTargetAtAddress(address, |
| 534 *pre_monomorphic_stub( | 535 *pre_monomorphic_stub( |
| 535 isolate, Code::GetStrictMode(target->extra_ic_state()))); | 536 isolate, StoreIC::GetStrictMode(target->extra_ic_state()))); |
| 536 } | 537 } |
| 537 | 538 |
| 538 | 539 |
| 539 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { | 540 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { |
| 540 if (IsCleared(target)) return; | 541 if (IsCleared(target)) return; |
| 541 SetTargetAtAddress(address, | 542 SetTargetAtAddress(address, |
| 542 *pre_monomorphic_stub( | 543 *pre_monomorphic_stub( |
| 543 isolate, Code::GetStrictMode(target->extra_ic_state()))); | 544 isolate, StoreIC::GetStrictMode(target->extra_ic_state()))); |
| 544 } | 545 } |
| 545 | 546 |
| 546 | 547 |
| 547 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { | 548 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { |
| 548 ASSERT(target->major_key() == CodeStub::CompareIC); | 549 ASSERT(target->major_key() == CodeStub::CompareIC); |
| 549 CompareIC::State handler_state; | 550 CompareIC::State handler_state; |
| 550 Token::Value op; | 551 Token::Value op; |
| 551 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, | 552 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, |
| 552 &handler_state, &op); | 553 &handler_state, &op); |
| 553 // Only clear CompareICs that can retain objects. | 554 // Only clear CompareICs that can retain objects. |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 ElementsKind kind = array->map()->elements_kind(); | 816 ElementsKind kind = array->map()->elements_kind(); |
| 816 if (IsFastObjectElementsKind(kind) && | 817 if (IsFastObjectElementsKind(kind) && |
| 817 array->map() == isolate()->get_initial_js_array_map(kind)) { | 818 array->map() == isolate()->get_initial_js_array_map(kind)) { |
| 818 KeyedArrayCallStub stub_gen(IsHoleyElementsKind(kind), argc); | 819 KeyedArrayCallStub stub_gen(IsHoleyElementsKind(kind), argc); |
| 819 stub = stub_gen.GetCode(isolate()); | 820 stub = stub_gen.GetCode(isolate()); |
| 820 } | 821 } |
| 821 } | 822 } |
| 822 | 823 |
| 823 if (stub.is_null()) { | 824 if (stub.is_null()) { |
| 824 stub = isolate()->stub_cache()->ComputeCallMegamorphic( | 825 stub = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 825 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 826 argc, Code::KEYED_CALL_IC, kNoExtraICState); |
| 826 if (object->IsJSObject()) { | 827 if (object->IsJSObject()) { |
| 827 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 828 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 828 if (receiver->elements()->map() == | 829 if (receiver->elements()->map() == |
| 829 isolate()->heap()->non_strict_arguments_elements_map()) { | 830 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 830 stub = isolate()->stub_cache()->ComputeCallArguments(argc); | 831 stub = isolate()->stub_cache()->ComputeCallArguments(argc); |
| 831 } | 832 } |
| 832 } | 833 } |
| 833 ASSERT(!stub.is_null()); | 834 ASSERT(!stub.is_null()); |
| 834 } | 835 } |
| 835 set_target(*stub); | 836 set_target(*stub); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 stub = pre_monomorphic_stub(); | 873 stub = pre_monomorphic_stub(); |
| 873 } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) { | 874 } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) { |
| 874 StringLengthStub string_length_stub(kind()); | 875 StringLengthStub string_length_stub(kind()); |
| 875 stub = string_length_stub.GetCode(isolate()); | 876 stub = string_length_stub.GetCode(isolate()); |
| 876 } else if (state() != MEGAMORPHIC) { | 877 } else if (state() != MEGAMORPHIC) { |
| 877 ASSERT(state() != GENERIC); | 878 ASSERT(state() != GENERIC); |
| 878 stub = megamorphic_stub(); | 879 stub = megamorphic_stub(); |
| 879 } | 880 } |
| 880 if (!stub.is_null()) { | 881 if (!stub.is_null()) { |
| 881 set_target(*stub); | 882 set_target(*stub); |
| 882 #ifdef DEBUG | |
| 883 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); | 883 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); |
| 884 #endif | |
| 885 } | 884 } |
| 886 // Get the string if we have a string wrapper object. | 885 // Get the string if we have a string wrapper object. |
| 887 String* string = String::cast(JSValue::cast(*object)->value()); | 886 String* string = String::cast(JSValue::cast(*object)->value()); |
| 888 return Smi::FromInt(string->length()); | 887 return Smi::FromInt(string->length()); |
| 889 } | 888 } |
| 890 | 889 |
| 891 // Use specialized code for getting prototype of functions. | 890 // Use specialized code for getting prototype of functions. |
| 892 if (object->IsJSFunction() && | 891 if (object->IsJSFunction() && |
| 893 name->Equals(isolate()->heap()->prototype_string()) && | 892 name->Equals(isolate()->heap()->prototype_string()) && |
| 894 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 893 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
| 895 Handle<Code> stub; | 894 Handle<Code> stub; |
| 896 if (state() == UNINITIALIZED) { | 895 if (state() == UNINITIALIZED) { |
| 897 stub = pre_monomorphic_stub(); | 896 stub = pre_monomorphic_stub(); |
| 898 } else if (state() == PREMONOMORPHIC) { | 897 } else if (state() == PREMONOMORPHIC) { |
| 899 FunctionPrototypeStub function_prototype_stub(kind()); | 898 FunctionPrototypeStub function_prototype_stub(kind()); |
| 900 stub = function_prototype_stub.GetCode(isolate()); | 899 stub = function_prototype_stub.GetCode(isolate()); |
| 901 } else if (state() != MEGAMORPHIC) { | 900 } else if (state() != MEGAMORPHIC) { |
| 902 ASSERT(state() != GENERIC); | 901 ASSERT(state() != GENERIC); |
| 903 stub = megamorphic_stub(); | 902 stub = megamorphic_stub(); |
| 904 } | 903 } |
| 905 if (!stub.is_null()) { | 904 if (!stub.is_null()) { |
| 906 set_target(*stub); | 905 set_target(*stub); |
| 907 #ifdef DEBUG | |
| 908 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 906 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); |
| 909 #endif | |
| 910 } | 907 } |
| 911 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); | 908 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); |
| 912 } | 909 } |
| 913 } | 910 } |
| 914 | 911 |
| 915 // Check if the name is trivially convertible to an index and get | 912 // Check if the name is trivially convertible to an index and get |
| 916 // the element or char if so. | 913 // the element or char if so. |
| 917 uint32_t index; | 914 uint32_t index; |
| 918 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 915 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
| 919 // Rewrite to the generic keyed load stub. | 916 // Rewrite to the generic keyed load stub. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 | 999 |
| 1003 number_of_valid_types++; | 1000 number_of_valid_types++; |
| 1004 if (handler_to_overwrite >= 0) { | 1001 if (handler_to_overwrite >= 0) { |
| 1005 handlers.Set(handler_to_overwrite, code); | 1002 handlers.Set(handler_to_overwrite, code); |
| 1006 } else { | 1003 } else { |
| 1007 types.Add(type); | 1004 types.Add(type); |
| 1008 handlers.Add(code); | 1005 handlers.Add(code); |
| 1009 } | 1006 } |
| 1010 | 1007 |
| 1011 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 1008 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
| 1012 &types, &handlers, number_of_valid_types, name, strict_mode()); | 1009 &types, &handlers, number_of_valid_types, name, extra_ic_state()); |
| 1013 set_target(*ic); | 1010 set_target(*ic); |
| 1014 return true; | 1011 return true; |
| 1015 } | 1012 } |
| 1016 | 1013 |
| 1017 | 1014 |
| 1018 Handle<Type> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { | 1015 Handle<Type> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { |
| 1019 Type* type = object->IsJSGlobalObject() | 1016 Type* type = object->IsJSGlobalObject() |
| 1020 ? Type::Constant(Handle<JSGlobalObject>::cast(object)) | 1017 ? Type::Constant(Handle<JSGlobalObject>::cast(object)) |
| 1021 : Type::OfCurrently(object); | 1018 : Type::OfCurrently(object); |
| 1022 return handle(type, isolate); | 1019 return handle(type, isolate); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1040 if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean(); | 1037 if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean(); |
| 1041 return Type::Class(map); | 1038 return Type::Class(map); |
| 1042 } | 1039 } |
| 1043 | 1040 |
| 1044 | 1041 |
| 1045 void IC::UpdateMonomorphicIC(Handle<Type> type, | 1042 void IC::UpdateMonomorphicIC(Handle<Type> type, |
| 1046 Handle<Code> handler, | 1043 Handle<Code> handler, |
| 1047 Handle<String> name) { | 1044 Handle<String> name) { |
| 1048 if (!handler->is_handler()) return set_target(*handler); | 1045 if (!handler->is_handler()) return set_target(*handler); |
| 1049 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( | 1046 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
| 1050 name, type, handler, strict_mode()); | 1047 name, type, handler, extra_ic_state()); |
| 1051 set_target(*ic); | 1048 set_target(*ic); |
| 1052 } | 1049 } |
| 1053 | 1050 |
| 1054 | 1051 |
| 1055 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 1052 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
| 1056 TypeHandleList types; | 1053 TypeHandleList types; |
| 1057 CodeHandleList handlers; | 1054 CodeHandleList handlers; |
| 1058 target()->FindAllTypes(&types); | 1055 target()->FindAllTypes(&types); |
| 1059 if (!target()->FindHandlers(&handlers, types.length())) return; | 1056 if (!target()->FindHandlers(&handlers, types.length())) return; |
| 1060 for (int i = 0; i < types.length(); i++) { | 1057 for (int i = 0; i < types.length(); i++) { |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1175 | 1172 |
| 1176 Handle<Code> IC::ComputeHandler(LookupResult* lookup, | 1173 Handle<Code> IC::ComputeHandler(LookupResult* lookup, |
| 1177 Handle<Object> object, | 1174 Handle<Object> object, |
| 1178 Handle<String> name, | 1175 Handle<String> name, |
| 1179 Handle<Object> value) { | 1176 Handle<Object> value) { |
| 1180 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object); | 1177 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object); |
| 1181 Handle<HeapObject> stub_holder(GetCodeCacheHolder( | 1178 Handle<HeapObject> stub_holder(GetCodeCacheHolder( |
| 1182 isolate(), *object, cache_holder)); | 1179 isolate(), *object, cache_holder)); |
| 1183 | 1180 |
| 1184 Handle<Code> code = isolate()->stub_cache()->FindHandler( | 1181 Handle<Code> code = isolate()->stub_cache()->FindHandler( |
| 1185 name, handle(stub_holder->map()), kind(), cache_holder, strict_mode()); | 1182 name, handle(stub_holder->map()), kind(), cache_holder); |
| 1186 if (!code.is_null()) return code; | 1183 if (!code.is_null()) return code; |
| 1187 | 1184 |
| 1188 code = CompileHandler(lookup, object, name, value, cache_holder); | 1185 code = CompileHandler(lookup, object, name, value, cache_holder); |
| 1189 ASSERT(code->is_handler()); | 1186 ASSERT(code->is_handler()); |
| 1190 | 1187 |
| 1191 if (code->type() != Code::NORMAL) { | 1188 if (code->type() != Code::NORMAL) { |
| 1192 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | 1189 HeapObject::UpdateMapCodeCache(stub_holder, name, code); |
| 1193 } | 1190 } |
| 1194 | 1191 |
| 1195 return code; | 1192 return code; |
| (...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1630 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, | 1627 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, |
| 1631 Handle<Object> object, | 1628 Handle<Object> object, |
| 1632 Handle<String> name, | 1629 Handle<String> name, |
| 1633 Handle<Object> value, | 1630 Handle<Object> value, |
| 1634 InlineCacheHolderFlag cache_holder) { | 1631 InlineCacheHolderFlag cache_holder) { |
| 1635 ASSERT(cache_holder == OWN_MAP); | 1632 ASSERT(cache_holder == OWN_MAP); |
| 1636 // This is currently guaranteed by checks in StoreIC::Store. | 1633 // This is currently guaranteed by checks in StoreIC::Store. |
| 1637 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1634 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1638 | 1635 |
| 1639 Handle<JSObject> holder(lookup->holder()); | 1636 Handle<JSObject> holder(lookup->holder()); |
| 1640 StoreStubCompiler compiler(isolate(), strict_mode(), kind()); | 1637 // Handlers do not use strict mode. |
| 1638 StoreStubCompiler compiler(isolate(), kNonStrictMode, kind()); |
| 1641 switch (lookup->type()) { | 1639 switch (lookup->type()) { |
| 1642 case FIELD: | 1640 case FIELD: |
| 1643 return compiler.CompileStoreField(receiver, lookup, name); | 1641 return compiler.CompileStoreField(receiver, lookup, name); |
| 1644 case TRANSITION: { | 1642 case TRANSITION: { |
| 1645 // Explicitly pass in the receiver map since LookupForWrite may have | 1643 // Explicitly pass in the receiver map since LookupForWrite may have |
| 1646 // stored something else than the receiver in the holder. | 1644 // stored something else than the receiver in the holder. |
| 1647 Handle<Map> transition( | 1645 Handle<Map> transition( |
| 1648 lookup->GetTransitionTarget(receiver->map()), isolate()); | 1646 lookup->GetTransitionTarget(receiver->map()), isolate()); |
| 1649 int descriptor = transition->LastAdded(); | 1647 int descriptor = transition->LastAdded(); |
| 1650 | 1648 |
| 1651 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 1649 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
| 1652 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 1650 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
| 1653 | 1651 |
| 1654 if (details.type() == CALLBACKS || details.attributes() != NONE) break; | 1652 if (details.type() == CALLBACKS || details.attributes() != NONE) break; |
| 1655 | 1653 |
| 1656 return compiler.CompileStoreTransition( | 1654 return compiler.CompileStoreTransition( |
| 1657 receiver, lookup, transition, name); | 1655 receiver, lookup, transition, name); |
| 1658 } | 1656 } |
| 1659 case NORMAL: | 1657 case NORMAL: |
| 1660 if (kind() == Code::KEYED_STORE_IC) break; | 1658 if (kind() == Code::KEYED_STORE_IC) break; |
| 1661 if (receiver->IsGlobalObject()) { | 1659 if (receiver->IsGlobalObject()) { |
| 1662 // The stub generated for the global object picks the value directly | 1660 // The stub generated for the global object picks the value directly |
| 1663 // from the property cell. So the property must be directly on the | 1661 // from the property cell. So the property must be directly on the |
| 1664 // global object. | 1662 // global object. |
| 1665 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1663 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); |
| 1666 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); | 1664 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); |
| 1667 Handle<Type> union_type = PropertyCell::UpdatedType(cell, value); | 1665 Handle<Type> union_type = PropertyCell::UpdatedType(cell, value); |
| 1668 StoreGlobalStub stub(strict_mode(), union_type->IsConstant()); | 1666 StoreGlobalStub stub(union_type->IsConstant()); |
| 1669 | 1667 |
| 1670 Handle<Code> code = stub.GetCodeCopyFromTemplate( | 1668 Handle<Code> code = stub.GetCodeCopyFromTemplate( |
| 1671 isolate(), receiver->map(), *cell); | 1669 isolate(), receiver->map(), *cell); |
| 1672 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1670 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
| 1673 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1671 HeapObject::UpdateMapCodeCache(receiver, name, code); |
| 1674 return code; | 1672 return code; |
| 1675 } | 1673 } |
| 1676 ASSERT(holder.is_identical_to(receiver)); | 1674 ASSERT(holder.is_identical_to(receiver)); |
| 1677 return strict_mode() == kStrictMode | 1675 return isolate()->builtins()->StoreIC_Normal(); |
| 1678 ? isolate()->builtins()->StoreIC_Normal_Strict() | |
| 1679 : isolate()->builtins()->StoreIC_Normal(); | |
| 1680 case CALLBACKS: { | 1676 case CALLBACKS: { |
| 1681 if (kind() == Code::KEYED_STORE_IC) break; | 1677 if (kind() == Code::KEYED_STORE_IC) break; |
| 1682 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1678 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
| 1683 if (callback->IsExecutableAccessorInfo()) { | 1679 if (callback->IsExecutableAccessorInfo()) { |
| 1684 Handle<ExecutableAccessorInfo> info = | 1680 Handle<ExecutableAccessorInfo> info = |
| 1685 Handle<ExecutableAccessorInfo>::cast(callback); | 1681 Handle<ExecutableAccessorInfo>::cast(callback); |
| 1686 if (v8::ToCData<Address>(info->setter()) == 0) break; | 1682 if (v8::ToCData<Address>(info->setter()) == 0) break; |
| 1687 if (!holder->HasFastProperties()) break; | 1683 if (!holder->HasFastProperties()) break; |
| 1688 if (!info->IsCompatibleReceiver(*receiver)) break; | 1684 if (!info->IsCompatibleReceiver(*receiver)) break; |
| 1689 return compiler.CompileStoreCallback(receiver, holder, name, info); | 1685 return compiler.CompileStoreCallback(receiver, holder, name, info); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1751 // stores into properties in dictionary mode), then there will be not | 1747 // stores into properties in dictionary mode), then there will be not |
| 1752 // receiver maps in the target. | 1748 // receiver maps in the target. |
| 1753 return generic_stub(); | 1749 return generic_stub(); |
| 1754 } | 1750 } |
| 1755 | 1751 |
| 1756 // There are several special cases where an IC that is MONOMORPHIC can still | 1752 // There are several special cases where an IC that is MONOMORPHIC can still |
| 1757 // transition to a different GetNonTransitioningStoreMode IC that handles a | 1753 // transition to a different GetNonTransitioningStoreMode IC that handles a |
| 1758 // superset of the original IC. Handle those here if the receiver map hasn't | 1754 // superset of the original IC. Handle those here if the receiver map hasn't |
| 1759 // changed or it has transitioned to a more general kind. | 1755 // changed or it has transitioned to a more general kind. |
| 1760 KeyedAccessStoreMode old_store_mode = | 1756 KeyedAccessStoreMode old_store_mode = |
| 1761 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); | 1757 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); |
| 1762 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | 1758 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); |
| 1763 if (state() == MONOMORPHIC) { | 1759 if (state() == MONOMORPHIC) { |
| 1764 // If the "old" and "new" maps are in the same elements map family, stay | 1760 // If the "old" and "new" maps are in the same elements map family, stay |
| 1765 // MONOMORPHIC and use the map for the most generic ElementsKind. | 1761 // MONOMORPHIC and use the map for the most generic ElementsKind. |
| 1766 Handle<Map> transitioned_receiver_map = receiver_map; | 1762 Handle<Map> transitioned_receiver_map = receiver_map; |
| 1767 if (IsTransitionStoreMode(store_mode)) { | 1763 if (IsTransitionStoreMode(store_mode)) { |
| 1768 transitioned_receiver_map = | 1764 transitioned_receiver_map = |
| 1769 ComputeTransitionedMap(receiver, store_mode); | 1765 ComputeTransitionedMap(receiver, store_mode); |
| 1770 } | 1766 } |
| 1771 if (IsTransitionOfMonomorphicTarget(MapToType(transitioned_receiver_map))) { | 1767 if (IsTransitionOfMonomorphicTarget(MapToType(transitioned_receiver_map))) { |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2342 case NUMBER: return "Number"; | 2338 case NUMBER: return "Number"; |
| 2343 case ODDBALL: return "Oddball"; | 2339 case ODDBALL: return "Oddball"; |
| 2344 case STRING: return "String"; | 2340 case STRING: return "String"; |
| 2345 case GENERIC: return "Generic"; | 2341 case GENERIC: return "Generic"; |
| 2346 default: return "Invalid"; | 2342 default: return "Invalid"; |
| 2347 } | 2343 } |
| 2348 } | 2344 } |
| 2349 | 2345 |
| 2350 | 2346 |
| 2351 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) { | 2347 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) { |
| 2352 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state(); | 2348 ExtraICState extra_ic_state = target()->extended_extra_ic_state(); |
| 2353 BinaryOpStub stub(extra_ic_state); | 2349 BinaryOpStub stub(extra_ic_state); |
| 2354 | 2350 |
| 2355 Handle<Type> left_type = stub.GetLeftType(isolate()); | 2351 Handle<Type> left_type = stub.GetLeftType(isolate()); |
| 2356 Handle<Type> right_type = stub.GetRightType(isolate()); | 2352 Handle<Type> right_type = stub.GetRightType(isolate()); |
| 2357 bool smi_was_enabled = left_type->Maybe(Type::Smi()) && | 2353 bool smi_was_enabled = left_type->Maybe(Type::Smi()) && |
| 2358 right_type->Maybe(Type::Smi()); | 2354 right_type->Maybe(Type::Smi()); |
| 2359 | 2355 |
| 2360 Maybe<Handle<Object> > result = stub.Result(left, right, isolate()); | 2356 Maybe<Handle<Object> > result = stub.Result(left, right, isolate()); |
| 2361 if (!result.has_value) return Failure::Exception(); | 2357 if (!result.has_value) return Failure::Exception(); |
| 2362 | 2358 |
| 2363 #ifdef DEBUG | |
| 2364 if (FLAG_trace_ic) { | 2359 if (FLAG_trace_ic) { |
| 2365 char buffer[100]; | 2360 char buffer[100]; |
| 2366 NoAllocationStringAllocator allocator(buffer, | 2361 NoAllocationStringAllocator allocator(buffer, |
| 2367 static_cast<unsigned>(sizeof(buffer))); | 2362 static_cast<unsigned>(sizeof(buffer))); |
| 2368 StringStream stream(&allocator); | 2363 StringStream stream(&allocator); |
| 2369 stream.Add("["); | 2364 stream.Add("["); |
| 2370 stub.PrintName(&stream); | 2365 stub.PrintName(&stream); |
| 2371 | 2366 |
| 2372 stub.UpdateStatus(left, right, result); | 2367 stub.UpdateStatus(left, right, result); |
| 2373 | 2368 |
| 2374 stream.Add(" => "); | 2369 stream.Add(" => "); |
| 2375 stub.PrintState(&stream); | 2370 stub.PrintState(&stream); |
| 2376 stream.Add(" "); | 2371 stream.Add(" "); |
| 2377 stream.OutputToStdOut(); | 2372 stream.OutputToStdOut(); |
| 2378 PrintF(" @ %p <- ", static_cast<void*>(*stub.GetCode(isolate()))); | 2373 PrintF(" @ %p <- ", static_cast<void*>(*stub.GetCode(isolate()))); |
| 2379 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2374 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
| 2380 PrintF("]\n"); | 2375 PrintF("]\n"); |
| 2381 } else { | 2376 } else { |
| 2382 stub.UpdateStatus(left, right, result); | 2377 stub.UpdateStatus(left, right, result); |
| 2383 } | 2378 } |
| 2384 #else | |
| 2385 stub.UpdateStatus(left, right, result); | |
| 2386 #endif | |
| 2387 | 2379 |
| 2388 Handle<Code> code = stub.GetCode(isolate()); | 2380 Handle<Code> code = stub.GetCode(isolate()); |
| 2389 set_target(*code); | 2381 set_target(*code); |
| 2390 | 2382 |
| 2391 left_type = stub.GetLeftType(isolate()); | 2383 left_type = stub.GetLeftType(isolate()); |
| 2392 right_type = stub.GetRightType(isolate()); | 2384 right_type = stub.GetRightType(isolate()); |
| 2393 bool enable_smi = left_type->Maybe(Type::Smi()) && | 2385 bool enable_smi = left_type->Maybe(Type::Smi()) && |
| 2394 right_type->Maybe(Type::Smi()); | 2386 right_type->Maybe(Type::Smi()); |
| 2395 | 2387 |
| 2396 if (!smi_was_enabled && enable_smi) { | 2388 if (!smi_was_enabled && enable_smi) { |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2605 State state = TargetState(previous_state, previous_left, previous_right, | 2597 State state = TargetState(previous_state, previous_left, previous_right, |
| 2606 HasInlinedSmiCode(address()), x, y); | 2598 HasInlinedSmiCode(address()), x, y); |
| 2607 ICCompareStub stub(op_, new_left, new_right, state); | 2599 ICCompareStub stub(op_, new_left, new_right, state); |
| 2608 if (state == KNOWN_OBJECT) { | 2600 if (state == KNOWN_OBJECT) { |
| 2609 stub.set_known_map( | 2601 stub.set_known_map( |
| 2610 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); | 2602 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); |
| 2611 } | 2603 } |
| 2612 Handle<Code> new_target = stub.GetCode(isolate()); | 2604 Handle<Code> new_target = stub.GetCode(isolate()); |
| 2613 set_target(*new_target); | 2605 set_target(*new_target); |
| 2614 | 2606 |
| 2615 #ifdef DEBUG | |
| 2616 if (FLAG_trace_ic) { | 2607 if (FLAG_trace_ic) { |
| 2617 PrintF("[CompareIC in "); | 2608 PrintF("[CompareIC in "); |
| 2618 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2609 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
| 2619 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", | 2610 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", |
| 2620 GetStateName(previous_left), | 2611 GetStateName(previous_left), |
| 2621 GetStateName(previous_right), | 2612 GetStateName(previous_right), |
| 2622 GetStateName(previous_state), | 2613 GetStateName(previous_state), |
| 2623 GetStateName(new_left), | 2614 GetStateName(new_left), |
| 2624 GetStateName(new_right), | 2615 GetStateName(new_right), |
| 2625 GetStateName(state), | 2616 GetStateName(state), |
| 2626 Token::Name(op_), | 2617 Token::Name(op_), |
| 2627 static_cast<void*>(*stub.GetCode(isolate()))); | 2618 static_cast<void*>(*stub.GetCode(isolate()))); |
| 2628 } | 2619 } |
| 2629 #endif | |
| 2630 | 2620 |
| 2631 // Activate inlined smi code. | 2621 // Activate inlined smi code. |
| 2632 if (previous_state == UNINITIALIZED) { | 2622 if (previous_state == UNINITIALIZED) { |
| 2633 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); | 2623 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); |
| 2634 } | 2624 } |
| 2635 | 2625 |
| 2636 return *new_target; | 2626 return *new_target; |
| 2637 } | 2627 } |
| 2638 | 2628 |
| 2639 | 2629 |
| 2640 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. | 2630 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. |
| 2641 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { | 2631 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { |
| 2642 HandleScope scope(isolate); | 2632 HandleScope scope(isolate); |
| 2643 ASSERT(args.length() == 3); | 2633 ASSERT(args.length() == 3); |
| 2644 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); | 2634 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); |
| 2645 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2635 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
| 2646 } | 2636 } |
| 2647 | 2637 |
| 2648 | 2638 |
| 2649 void CompareNilIC::Clear(Address address, Code* target) { | 2639 void CompareNilIC::Clear(Address address, Code* target) { |
| 2650 if (IsCleared(target)) return; | 2640 if (IsCleared(target)) return; |
| 2651 Code::ExtraICState state = target->extended_extra_ic_state(); | 2641 ExtraICState state = target->extended_extra_ic_state(); |
| 2652 | 2642 |
| 2653 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); | 2643 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); |
| 2654 stub.ClearState(); | 2644 stub.ClearState(); |
| 2655 | 2645 |
| 2656 Code* code = NULL; | 2646 Code* code = NULL; |
| 2657 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); | 2647 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); |
| 2658 | 2648 |
| 2659 SetTargetAtAddress(address, code); | 2649 SetTargetAtAddress(address, code); |
| 2660 } | 2650 } |
| 2661 | 2651 |
| 2662 | 2652 |
| 2663 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, | 2653 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, |
| 2664 Handle<Object> object) { | 2654 Handle<Object> object) { |
| 2665 if (object->IsNull() || object->IsUndefined()) { | 2655 if (object->IsNull() || object->IsUndefined()) { |
| 2666 return Smi::FromInt(true); | 2656 return Smi::FromInt(true); |
| 2667 } | 2657 } |
| 2668 return Smi::FromInt(object->IsUndetectableObject()); | 2658 return Smi::FromInt(object->IsUndetectableObject()); |
| 2669 } | 2659 } |
| 2670 | 2660 |
| 2671 | 2661 |
| 2672 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) { | 2662 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) { |
| 2673 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state(); | 2663 ExtraICState extra_ic_state = target()->extended_extra_ic_state(); |
| 2674 | 2664 |
| 2675 CompareNilICStub stub(extra_ic_state); | 2665 CompareNilICStub stub(extra_ic_state); |
| 2676 | 2666 |
| 2677 // Extract the current supported types from the patched IC and calculate what | 2667 // Extract the current supported types from the patched IC and calculate what |
| 2678 // types must be supported as a result of the miss. | 2668 // types must be supported as a result of the miss. |
| 2679 bool already_monomorphic = stub.IsMonomorphic(); | 2669 bool already_monomorphic = stub.IsMonomorphic(); |
| 2680 | 2670 |
| 2681 stub.UpdateStatus(object); | 2671 stub.UpdateStatus(object); |
| 2682 | 2672 |
| 2683 NilValue nil = stub.GetNilValue(); | 2673 NilValue nil = stub.GetNilValue(); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2778 #undef ADDR | 2768 #undef ADDR |
| 2779 }; | 2769 }; |
| 2780 | 2770 |
| 2781 | 2771 |
| 2782 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2772 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2783 return IC_utilities[id]; | 2773 return IC_utilities[id]; |
| 2784 } | 2774 } |
| 2785 | 2775 |
| 2786 | 2776 |
| 2787 } } // namespace v8::internal | 2777 } } // namespace v8::internal |
| OLD | NEW |