| 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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ | 111 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ |
| 112 PrintF(" (%s)]\n", reason); \ | 112 PrintF(" (%s)]\n", reason); \ |
| 113 } \ | 113 } \ |
| 114 } while (false) | 114 } while (false) |
| 115 | 115 |
| 116 #else | 116 #else |
| 117 #define TRACE_GENERIC_IC(isolate, type, reason) | 117 #define TRACE_GENERIC_IC(isolate, type, reason) |
| 118 #endif // DEBUG | 118 #endif // DEBUG |
| 119 | 119 |
| 120 #define TRACE_IC(type, name, old_state, new_target) \ | 120 #define TRACE_IC(type, name, old_state, new_target) \ |
| 121 ASSERT((TraceIC(type, name, old_state, new_target), true)) | 121 ASSERT((TraceIC(type, name, old_state, *new_target), true)) |
| 122 | 122 |
| 123 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { | 123 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { |
| 124 // To improve the performance of the (much used) IC code, we unfold a few | 124 // To improve the performance of the (much used) IC code, we unfold a few |
| 125 // levels of the stack frame iteration code. This yields a ~35% speedup when | 125 // levels of the stack frame iteration code. This yields a ~35% speedup when |
| 126 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 126 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
| 127 const Address entry = | 127 const Address entry = |
| 128 Isolate::c_entry_fp(isolate->thread_local_top()); | 128 Isolate::c_entry_fp(isolate->thread_local_top()); |
| 129 Address* pc_address = | 129 Address* pc_address = |
| 130 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); | 130 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); |
| 131 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 131 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
| 132 // If there's another JavaScript frame on the stack or a | 132 // If there's another JavaScript frame on the stack or a |
| 133 // StubFailureTrampoline, we need to look one frame further down the stack to | 133 // StubFailureTrampoline, we need to look one frame further down the stack to |
| 134 // find the frame pointer and the return address stack slot. | 134 // find the frame pointer and the return address stack slot. |
| 135 if (depth == EXTRA_CALL_FRAME) { | 135 if (depth == EXTRA_CALL_FRAME) { |
| 136 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; | 136 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; |
| 137 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); | 137 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); |
| 138 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); | 138 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); |
| 139 } | 139 } |
| 140 #ifdef DEBUG | 140 #ifdef DEBUG |
| 141 StackFrameIterator it(isolate); | 141 StackFrameIterator it(isolate); |
| 142 for (int i = 0; i < depth + 1; i++) it.Advance(); | 142 for (int i = 0; i < depth + 1; i++) it.Advance(); |
| 143 StackFrame* frame = it.frame(); | 143 StackFrame* frame = it.frame(); |
| 144 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); | 144 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); |
| 145 #endif | 145 #endif |
| 146 fp_ = fp; | 146 fp_ = fp; |
| 147 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 147 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); |
| 148 target_ = handle(raw_target(), isolate); |
| 148 } | 149 } |
| 149 | 150 |
| 150 | 151 |
| 151 #ifdef ENABLE_DEBUGGER_SUPPORT | 152 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 152 Address IC::OriginalCodeAddress() const { | 153 Address IC::OriginalCodeAddress() const { |
| 153 HandleScope scope(isolate()); | 154 HandleScope scope(isolate()); |
| 154 // Compute the JavaScript frame for the frame pointer of this IC | 155 // Compute the JavaScript frame for the frame pointer of this IC |
| 155 // structure. We need this to be able to find the function | 156 // structure. We need this to be able to find the function |
| 156 // corresponding to the frame. | 157 // corresponding to the frame. |
| 157 StackFrameIterator it(isolate()); | 158 StackFrameIterator it(isolate()); |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 // This is the first time we execute this inline cache. | 746 // This is the first time we execute this inline cache. |
| 746 // Set the target to the pre monomorphic stub to delay | 747 // Set the target to the pre monomorphic stub to delay |
| 747 // setting the monomorphic state. | 748 // setting the monomorphic state. |
| 748 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( | 749 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( |
| 749 argc, kind_, extra_ic_state); | 750 argc, kind_, extra_ic_state); |
| 750 } else if (state == MONOMORPHIC) { | 751 } else if (state == MONOMORPHIC) { |
| 751 if (kind_ == Code::CALL_IC && | 752 if (kind_ == Code::CALL_IC && |
| 752 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 753 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { |
| 753 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, | 754 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
| 754 object, name); | 755 object, name); |
| 755 } else if (TryRemoveInvalidPrototypeDependentStub(target(), | 756 } else if (TryRemoveInvalidPrototypeDependentStub(*target(), |
| 756 *object, | 757 *object, |
| 757 *name)) { | 758 *name)) { |
| 758 state = MONOMORPHIC_PROTOTYPE_FAILURE; | 759 state = MONOMORPHIC_PROTOTYPE_FAILURE; |
| 759 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, | 760 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
| 760 object, name); | 761 object, name); |
| 761 } else { | 762 } else { |
| 762 code = isolate()->stub_cache()->ComputeCallMegamorphic( | 763 code = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 763 argc, kind_, extra_ic_state); | 764 argc, kind_, extra_ic_state); |
| 764 } | 765 } |
| 765 } else { | 766 } else { |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 IsMoreGeneralElementsKindTransition( | 1081 IsMoreGeneralElementsKindTransition( |
| 1081 current_map->elements_kind(), receiver_elements_kind); | 1082 current_map->elements_kind(), receiver_elements_kind); |
| 1082 Map* transitioned_map = more_general_transition | 1083 Map* transitioned_map = more_general_transition |
| 1083 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) | 1084 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) |
| 1084 : NULL; | 1085 : NULL; |
| 1085 | 1086 |
| 1086 return transitioned_map == receiver_map; | 1087 return transitioned_map == receiver_map; |
| 1087 } | 1088 } |
| 1088 | 1089 |
| 1089 | 1090 |
| 1090 // Since GC may have been invoked, by the time PatchCache is called, |state| is | |
| 1091 // not necessarily equal to target()->state(). | |
| 1092 void IC::PatchCache(State state, | 1091 void IC::PatchCache(State state, |
| 1093 Handle<HeapObject> receiver, | 1092 Handle<HeapObject> receiver, |
| 1094 Handle<String> name, | 1093 Handle<String> name, |
| 1095 Handle<Code> code) { | 1094 Handle<Code> code) { |
| 1096 switch (state) { | 1095 switch (state) { |
| 1097 case UNINITIALIZED: | 1096 case UNINITIALIZED: |
| 1098 case PREMONOMORPHIC: | 1097 case PREMONOMORPHIC: |
| 1099 case MONOMORPHIC_PROTOTYPE_FAILURE: | 1098 case MONOMORPHIC_PROTOTYPE_FAILURE: |
| 1100 UpdateMonomorphicIC(receiver, code, name); | 1099 UpdateMonomorphicIC(receiver, code, name); |
| 1101 break; | 1100 break; |
| 1102 case MONOMORPHIC: | 1101 case MONOMORPHIC: |
| 1103 ASSERT(target() != *code); | 1102 ASSERT(!target().is_identical_to(code)); |
| 1104 if (!target()->is_keyed_stub()) { | 1103 if (!target()->is_keyed_stub()) { |
| 1105 bool is_same_handler = false; | 1104 bool is_same_handler = false; |
| 1106 { | 1105 { |
| 1107 DisallowHeapAllocation no_allocation; | 1106 DisallowHeapAllocation no_allocation; |
| 1108 Code* old_handler = target()->FindFirstHandler(); | 1107 Code* old_handler = target()->FindFirstHandler(); |
| 1109 is_same_handler = old_handler == *code; | 1108 is_same_handler = old_handler == *code; |
| 1110 } | 1109 } |
| 1111 if (is_same_handler | 1110 if (is_same_handler |
| 1112 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { | 1111 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { |
| 1113 UpdateMonomorphicIC(receiver, code, name); | 1112 UpdateMonomorphicIC(receiver, code, name); |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 } | 1357 } |
| 1359 | 1358 |
| 1360 Handle<Map> receiver_map(receiver->map(), isolate()); | 1359 Handle<Map> receiver_map(receiver->map(), isolate()); |
| 1361 MapHandleList target_receiver_maps; | 1360 MapHandleList target_receiver_maps; |
| 1362 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { | 1361 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { |
| 1363 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1362 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state |
| 1364 // yet will do so and stay there. | 1363 // yet will do so and stay there. |
| 1365 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1364 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
| 1366 } | 1365 } |
| 1367 | 1366 |
| 1368 if (target() == *string_stub()) { | 1367 if (target().is_identical_to(string_stub())) { |
| 1369 target_receiver_maps.Add(isolate()->factory()->string_map()); | 1368 target_receiver_maps.Add(isolate()->factory()->string_map()); |
| 1370 } else { | 1369 } else { |
| 1371 GetReceiverMapsForStub(Handle<Code>(target(), isolate()), | 1370 GetReceiverMapsForStub(target(), &target_receiver_maps); |
| 1372 &target_receiver_maps); | |
| 1373 if (target_receiver_maps.length() == 0) { | 1371 if (target_receiver_maps.length() == 0) { |
| 1374 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1372 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
| 1375 } | 1373 } |
| 1376 } | 1374 } |
| 1377 | 1375 |
| 1378 // The first time a receiver is seen that is a transitioned version of the | 1376 // The first time a receiver is seen that is a transitioned version of the |
| 1379 // previous monomorphic receiver type, assume the new ElementsKind is the | 1377 // previous monomorphic receiver type, assume the new ElementsKind is the |
| 1380 // monomorphic type. This benefits global arrays that only transition | 1378 // monomorphic type. This benefits global arrays that only transition |
| 1381 // once, and all call sites accessing them are faster if they remain | 1379 // once, and all call sites accessing them are faster if they remain |
| 1382 // monomorphic. If this optimistic assumption is not true, the IC will | 1380 // monomorphic. If this optimistic assumption is not true, the IC will |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1440 use_ic = false; | 1438 use_ic = false; |
| 1441 JSObject::MigrateInstance(receiver); | 1439 JSObject::MigrateInstance(receiver); |
| 1442 } | 1440 } |
| 1443 | 1441 |
| 1444 if (receiver->elements()->map() == | 1442 if (receiver->elements()->map() == |
| 1445 isolate()->heap()->non_strict_arguments_elements_map()) { | 1443 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1446 stub = non_strict_arguments_stub(); | 1444 stub = non_strict_arguments_stub(); |
| 1447 } else if (receiver->HasIndexedInterceptor()) { | 1445 } else if (receiver->HasIndexedInterceptor()) { |
| 1448 stub = indexed_interceptor_stub(); | 1446 stub = indexed_interceptor_stub(); |
| 1449 } else if (!key->ToSmi()->IsFailure() && | 1447 } else if (!key->ToSmi()->IsFailure() && |
| 1450 (target() != *non_strict_arguments_stub())) { | 1448 (!target().is_identical_to(non_strict_arguments_stub()))) { |
| 1451 stub = LoadElementStub(receiver); | 1449 stub = LoadElementStub(receiver); |
| 1452 } | 1450 } |
| 1453 } | 1451 } |
| 1454 } else { | 1452 } else { |
| 1455 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); | 1453 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); |
| 1456 } | 1454 } |
| 1457 if (use_ic) { | 1455 if (use_ic) { |
| 1458 ASSERT(!stub.is_null()); | 1456 ASSERT(!stub.is_null()); |
| 1459 set_target(*stub); | 1457 set_target(*stub); |
| 1460 TRACE_IC("KeyedLoadIC", key, state, target()); | 1458 TRACE_IC("KeyedLoadIC", key, state, target()); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1651 // to have fast properties but a read-only length. | 1649 // to have fast properties but a read-only length. |
| 1652 if (use_ic && | 1650 if (use_ic && |
| 1653 receiver->IsJSArray() && | 1651 receiver->IsJSArray() && |
| 1654 name->Equals(isolate()->heap()->length_string()) && | 1652 name->Equals(isolate()->heap()->length_string()) && |
| 1655 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1653 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
| 1656 receiver->HasFastProperties() && | 1654 receiver->HasFastProperties() && |
| 1657 !receiver->map()->is_frozen()) { | 1655 !receiver->map()->is_frozen()) { |
| 1658 Handle<Code> stub = | 1656 Handle<Code> stub = |
| 1659 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); | 1657 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); |
| 1660 set_target(*stub); | 1658 set_target(*stub); |
| 1661 TRACE_IC("StoreIC", name, state, *stub); | 1659 TRACE_IC("StoreIC", name, state, stub); |
| 1662 Handle<Object> result = JSReceiver::SetProperty( | 1660 Handle<Object> result = JSReceiver::SetProperty( |
| 1663 receiver, name, value, NONE, strict_mode(), store_mode); | 1661 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1664 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1662 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1665 return *result; | 1663 return *result; |
| 1666 } | 1664 } |
| 1667 | 1665 |
| 1668 if (receiver->IsJSGlobalProxy()) { | 1666 if (receiver->IsJSGlobalProxy()) { |
| 1669 if (use_ic && kind() != Code::KEYED_STORE_IC) { | 1667 if (use_ic && kind() != Code::KEYED_STORE_IC) { |
| 1670 // Generate a generic stub that goes to the runtime when we see a global | 1668 // Generate a generic stub that goes to the runtime when we see a global |
| 1671 // proxy as receiver. | 1669 // proxy as receiver. |
| 1672 Handle<Code> stub = global_proxy_stub(); | 1670 Handle<Code> stub = global_proxy_stub(); |
| 1673 set_target(*stub); | 1671 set_target(*stub); |
| 1674 TRACE_IC("StoreIC", name, state, *stub); | 1672 TRACE_IC("StoreIC", name, state, stub); |
| 1675 } | 1673 } |
| 1676 Handle<Object> result = JSReceiver::SetProperty( | 1674 Handle<Object> result = JSReceiver::SetProperty( |
| 1677 receiver, name, value, NONE, strict_mode(), store_mode); | 1675 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1678 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1676 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1679 return *result; | 1677 return *result; |
| 1680 } | 1678 } |
| 1681 | 1679 |
| 1682 LookupResult lookup(isolate()); | 1680 LookupResult lookup(isolate()); |
| 1683 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); | 1681 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); |
| 1684 if (!can_store && | 1682 if (!can_store && |
| 1685 strict_mode() == kStrictMode && | 1683 strict_mode() == kStrictMode && |
| 1686 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1684 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1687 IsUndeclaredGlobal(object)) { | 1685 IsUndeclaredGlobal(object)) { |
| 1688 // Strict mode doesn't allow setting non-existent global property. | 1686 // Strict mode doesn't allow setting non-existent global property. |
| 1689 return ReferenceError("not_defined", name); | 1687 return ReferenceError("not_defined", name); |
| 1690 } | 1688 } |
| 1691 if (use_ic) { | 1689 if (use_ic) { |
| 1692 if (state == UNINITIALIZED) { | 1690 if (state == UNINITIALIZED) { |
| 1693 Handle<Code> stub = pre_monomorphic_stub(); | 1691 Handle<Code> stub = pre_monomorphic_stub(); |
| 1694 set_target(*stub); | 1692 set_target(*stub); |
| 1695 TRACE_IC("StoreIC", name, state, *stub); | 1693 TRACE_IC("StoreIC", name, state, stub); |
| 1696 } else if (can_store) { | 1694 } else if (can_store) { |
| 1697 UpdateCaches(&lookup, state, receiver, name, value); | 1695 UpdateCaches(&lookup, state, receiver, name, value); |
| 1698 } else if (!name->IsCacheable(isolate()) || | 1696 } else if (!name->IsCacheable(isolate()) || |
| 1699 lookup.IsNormal() || | 1697 lookup.IsNormal() || |
| 1700 (lookup.IsField() && lookup.CanHoldValue(value))) { | 1698 (lookup.IsField() && lookup.CanHoldValue(value))) { |
| 1701 Handle<Code> stub = generic_stub(); | 1699 Handle<Code> stub = generic_stub(); |
| 1702 set_target(*stub); | 1700 set_target(*stub); |
| 1703 } | 1701 } |
| 1704 } | 1702 } |
| 1705 | 1703 |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2096 if (object->IsJSObject()) { | 2094 if (object->IsJSObject()) { |
| 2097 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 2095 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 2098 if (receiver->map()->is_deprecated()) { | 2096 if (receiver->map()->is_deprecated()) { |
| 2099 JSObject::MigrateInstance(receiver); | 2097 JSObject::MigrateInstance(receiver); |
| 2100 } | 2098 } |
| 2101 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); | 2099 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); |
| 2102 if (receiver->elements()->map() == | 2100 if (receiver->elements()->map() == |
| 2103 isolate()->heap()->non_strict_arguments_elements_map()) { | 2101 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 2104 stub = non_strict_arguments_stub(); | 2102 stub = non_strict_arguments_stub(); |
| 2105 } else if (key_is_smi_like && | 2103 } else if (key_is_smi_like && |
| 2106 (target() != *non_strict_arguments_stub())) { | 2104 (!target().is_identical_to(non_strict_arguments_stub()))) { |
| 2107 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); | 2105 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); |
| 2108 stub = StoreElementStub(receiver, store_mode); | 2106 stub = StoreElementStub(receiver, store_mode); |
| 2109 } else { | 2107 } else { |
| 2110 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); | 2108 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); |
| 2111 } | 2109 } |
| 2112 } else { | 2110 } else { |
| 2113 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object"); | 2111 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object"); |
| 2114 } | 2112 } |
| 2115 } else { | 2113 } else { |
| 2116 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); | 2114 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2173 | 2171 |
| 2174 // ---------------------------------------------------------------------------- | 2172 // ---------------------------------------------------------------------------- |
| 2175 // Static IC stub generators. | 2173 // Static IC stub generators. |
| 2176 // | 2174 // |
| 2177 | 2175 |
| 2178 // Used from ic-<arch>.cc. | 2176 // Used from ic-<arch>.cc. |
| 2179 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | 2177 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { |
| 2180 HandleScope scope(isolate); | 2178 HandleScope scope(isolate); |
| 2181 ASSERT(args.length() == 2); | 2179 ASSERT(args.length() == 2); |
| 2182 CallIC ic(isolate); | 2180 CallIC ic(isolate); |
| 2183 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2181 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2184 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2182 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
| 2185 MaybeObject* maybe_result = ic.LoadFunction(state, | 2183 MaybeObject* maybe_result = ic.LoadFunction(state, |
| 2186 extra_ic_state, | 2184 extra_ic_state, |
| 2187 args.at<Object>(0), | 2185 args.at<Object>(0), |
| 2188 args.at<String>(1)); | 2186 args.at<String>(1)); |
| 2189 JSFunction* raw_function; | 2187 JSFunction* raw_function; |
| 2190 if (!maybe_result->To(&raw_function)) return maybe_result; | 2188 if (!maybe_result->To(&raw_function)) return maybe_result; |
| 2191 | 2189 |
| 2192 // The first time the inline cache is updated may be the first time the | 2190 // The first time the inline cache is updated may be the first time the |
| 2193 // function it references gets called. If the function is lazily compiled | 2191 // function it references gets called. If the function is lazily compiled |
| 2194 // then the first call will trigger a compilation. We check for this case | 2192 // then the first call will trigger a compilation. We check for this case |
| 2195 // and we do the compilation immediately, instead of waiting for the stub | 2193 // and we do the compilation immediately, instead of waiting for the stub |
| 2196 // currently attached to the JSFunction object to trigger compilation. | 2194 // currently attached to the JSFunction object to trigger compilation. |
| 2197 if (raw_function->is_compiled()) return raw_function; | 2195 if (raw_function->is_compiled()) return raw_function; |
| 2198 | 2196 |
| 2199 Handle<JSFunction> function(raw_function); | 2197 Handle<JSFunction> function(raw_function); |
| 2200 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); | 2198 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); |
| 2201 return *function; | 2199 return *function; |
| 2202 } | 2200 } |
| 2203 | 2201 |
| 2204 | 2202 |
| 2205 // Used from ic-<arch>.cc. | 2203 // Used from ic-<arch>.cc. |
| 2206 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { | 2204 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { |
| 2207 HandleScope scope(isolate); | 2205 HandleScope scope(isolate); |
| 2208 ASSERT(args.length() == 2); | 2206 ASSERT(args.length() == 2); |
| 2209 KeyedCallIC ic(isolate); | 2207 KeyedCallIC ic(isolate); |
| 2210 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2208 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2211 MaybeObject* maybe_result = | 2209 MaybeObject* maybe_result = |
| 2212 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); | 2210 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); |
| 2213 // Result could be a function or a failure. | 2211 // Result could be a function or a failure. |
| 2214 JSFunction* raw_function = NULL; | 2212 JSFunction* raw_function = NULL; |
| 2215 if (!maybe_result->To(&raw_function)) return maybe_result; | 2213 if (!maybe_result->To(&raw_function)) return maybe_result; |
| 2216 | 2214 |
| 2217 if (raw_function->is_compiled()) return raw_function; | 2215 if (raw_function->is_compiled()) return raw_function; |
| 2218 | 2216 |
| 2219 Handle<JSFunction> function(raw_function, isolate); | 2217 Handle<JSFunction> function(raw_function, isolate); |
| 2220 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); | 2218 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); |
| 2221 return *function; | 2219 return *function; |
| 2222 } | 2220 } |
| 2223 | 2221 |
| 2224 | 2222 |
| 2225 // Used from ic-<arch>.cc. | 2223 // Used from ic-<arch>.cc. |
| 2226 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 2224 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
| 2227 HandleScope scope(isolate); | 2225 HandleScope scope(isolate); |
| 2228 ASSERT(args.length() == 2); | 2226 ASSERT(args.length() == 2); |
| 2229 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2227 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2230 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2228 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2231 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 2229 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); |
| 2232 } | 2230 } |
| 2233 | 2231 |
| 2234 | 2232 |
| 2235 // Used from ic-<arch>.cc | 2233 // Used from ic-<arch>.cc |
| 2236 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { | 2234 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { |
| 2237 HandleScope scope(isolate); | 2235 HandleScope scope(isolate); |
| 2238 ASSERT(args.length() == 2); | 2236 ASSERT(args.length() == 2); |
| 2239 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2237 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2240 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2238 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2241 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), MISS); | 2239 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), MISS); |
| 2242 } | 2240 } |
| 2243 | 2241 |
| 2244 | 2242 |
| 2245 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { | 2243 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { |
| 2246 HandleScope scope(isolate); | 2244 HandleScope scope(isolate); |
| 2247 ASSERT(args.length() == 2); | 2245 ASSERT(args.length() == 2); |
| 2248 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2246 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2249 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2247 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2250 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), MISS); | 2248 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), MISS); |
| 2251 } | 2249 } |
| 2252 | 2250 |
| 2253 | 2251 |
| 2254 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { | 2252 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { |
| 2255 HandleScope scope(isolate); | 2253 HandleScope scope(isolate); |
| 2256 ASSERT(args.length() == 2); | 2254 ASSERT(args.length() == 2); |
| 2257 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2255 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2258 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2256 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2259 return ic.Load(state, | 2257 return ic.Load(state, |
| 2260 args.at<Object>(0), | 2258 args.at<Object>(0), |
| 2261 args.at<Object>(1), | 2259 args.at<Object>(1), |
| 2262 MISS_FORCE_GENERIC); | 2260 MISS_FORCE_GENERIC); |
| 2263 } | 2261 } |
| 2264 | 2262 |
| 2265 | 2263 |
| 2266 // Used from ic-<arch>.cc. | 2264 // Used from ic-<arch>.cc. |
| 2267 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { | 2265 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { |
| 2268 HandleScope scope(isolate); | 2266 HandleScope scope(isolate); |
| 2269 ASSERT(args.length() == 3); | 2267 ASSERT(args.length() == 3); |
| 2270 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2268 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2271 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2269 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2272 return ic.Store(state, | 2270 return ic.Store(state, |
| 2273 args.at<Object>(0), | 2271 args.at<Object>(0), |
| 2274 args.at<String>(1), | 2272 args.at<String>(1), |
| 2275 args.at<Object>(2)); | 2273 args.at<Object>(2)); |
| 2276 } | 2274 } |
| 2277 | 2275 |
| 2278 | 2276 |
| 2279 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { | 2277 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { |
| 2280 HandleScope scope(isolate); | 2278 HandleScope scope(isolate); |
| 2281 ASSERT(args.length() == 3); | 2279 ASSERT(args.length() == 3); |
| 2282 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2280 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2283 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2281 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2284 return ic.Store(state, | 2282 return ic.Store(state, |
| 2285 args.at<Object>(0), | 2283 args.at<Object>(0), |
| 2286 args.at<String>(1), | 2284 args.at<String>(1), |
| 2287 args.at<Object>(2)); | 2285 args.at<Object>(2)); |
| 2288 } | 2286 } |
| 2289 | 2287 |
| 2290 | 2288 |
| 2291 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { | 2289 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { |
| 2292 SealHandleScope shs(isolate); | 2290 SealHandleScope shs(isolate); |
| 2293 | 2291 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2360 // Return the stored value. | 2358 // Return the stored value. |
| 2361 return value; | 2359 return value; |
| 2362 } | 2360 } |
| 2363 | 2361 |
| 2364 | 2362 |
| 2365 // Used from ic-<arch>.cc. | 2363 // Used from ic-<arch>.cc. |
| 2366 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { | 2364 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { |
| 2367 HandleScope scope(isolate); | 2365 HandleScope scope(isolate); |
| 2368 ASSERT(args.length() == 3); | 2366 ASSERT(args.length() == 3); |
| 2369 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2367 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2370 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2368 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2371 return ic.Store(state, | 2369 return ic.Store(state, |
| 2372 args.at<Object>(0), | 2370 args.at<Object>(0), |
| 2373 args.at<Object>(1), | 2371 args.at<Object>(1), |
| 2374 args.at<Object>(2), | 2372 args.at<Object>(2), |
| 2375 MISS); | 2373 MISS); |
| 2376 } | 2374 } |
| 2377 | 2375 |
| 2378 | 2376 |
| 2379 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { | 2377 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { |
| 2380 HandleScope scope(isolate); | 2378 HandleScope scope(isolate); |
| 2381 ASSERT(args.length() == 3); | 2379 ASSERT(args.length() == 3); |
| 2382 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2380 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2383 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2381 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2384 return ic.Store(state, | 2382 return ic.Store(state, |
| 2385 args.at<Object>(0), | 2383 args.at<Object>(0), |
| 2386 args.at<Object>(1), | 2384 args.at<Object>(1), |
| 2387 args.at<Object>(2), | 2385 args.at<Object>(2), |
| 2388 MISS); | 2386 MISS); |
| 2389 } | 2387 } |
| 2390 | 2388 |
| 2391 | 2389 |
| 2392 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { | 2390 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { |
| 2393 SealHandleScope shs(isolate); | 2391 HandleScope scope(isolate); |
| 2394 ASSERT(args.length() == 3); | 2392 ASSERT(args.length() == 3); |
| 2395 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2393 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2396 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2394 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
| 2397 Handle<Object> object = args.at<Object>(0); | 2395 Handle<Object> object = args.at<Object>(0); |
| 2398 Handle<Object> key = args.at<Object>(1); | 2396 Handle<Object> key = args.at<Object>(1); |
| 2399 Handle<Object> value = args.at<Object>(2); | 2397 Handle<Object> value = args.at<Object>(2); |
| 2400 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); | 2398 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); |
| 2401 return Runtime::SetObjectProperty(isolate, | 2399 return Runtime::SetObjectProperty(isolate, |
| 2402 object, | 2400 object, |
| 2403 key, | 2401 key, |
| 2404 value, | 2402 value, |
| 2405 NONE, | 2403 NONE, |
| 2406 strict_mode); | 2404 strict_mode); |
| 2407 } | 2405 } |
| 2408 | 2406 |
| 2409 | 2407 |
| 2410 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { | 2408 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { |
| 2411 SealHandleScope shs(isolate); | 2409 HandleScope scope(isolate); |
| 2412 ASSERT(args.length() == 3); | 2410 ASSERT(args.length() == 3); |
| 2413 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2411 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2414 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2412 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
| 2415 Handle<Object> object = args.at<Object>(0); | 2413 Handle<Object> object = args.at<Object>(0); |
| 2416 Handle<Object> key = args.at<Object>(1); | 2414 Handle<Object> key = args.at<Object>(1); |
| 2417 Handle<Object> value = args.at<Object>(2); | 2415 Handle<Object> value = args.at<Object>(2); |
| 2418 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); | 2416 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); |
| 2419 return Runtime::SetObjectProperty(isolate, | 2417 return Runtime::SetObjectProperty(isolate, |
| 2420 object, | 2418 object, |
| 2421 key, | 2419 key, |
| 2422 value, | 2420 value, |
| 2423 NONE, | 2421 NONE, |
| 2424 strict_mode); | 2422 strict_mode); |
| 2425 } | 2423 } |
| 2426 | 2424 |
| 2427 | 2425 |
| 2428 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { | 2426 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { |
| 2429 HandleScope scope(isolate); | 2427 HandleScope scope(isolate); |
| 2430 ASSERT(args.length() == 3); | 2428 ASSERT(args.length() == 3); |
| 2431 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2429 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2432 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2430 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); |
| 2433 return ic.Store(state, | 2431 return ic.Store(state, |
| 2434 args.at<Object>(0), | 2432 args.at<Object>(0), |
| 2435 args.at<Object>(1), | 2433 args.at<Object>(1), |
| 2436 args.at<Object>(2), | 2434 args.at<Object>(2), |
| 2437 MISS_FORCE_GENERIC); | 2435 MISS_FORCE_GENERIC); |
| 2438 } | 2436 } |
| 2439 | 2437 |
| 2440 | 2438 |
| 2441 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { | 2439 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { |
| 2442 SealHandleScope scope(isolate); | 2440 HandleScope scope(isolate); |
| 2443 ASSERT(args.length() == 4); | 2441 ASSERT(args.length() == 4); |
| 2444 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2442 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2445 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2443 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
| 2446 Handle<Object> value = args.at<Object>(0); | 2444 Handle<Object> value = args.at<Object>(0); |
| 2447 Handle<Object> key = args.at<Object>(2); | 2445 Handle<Object> key = args.at<Object>(2); |
| 2448 Handle<Object> object = args.at<Object>(3); | 2446 Handle<Object> object = args.at<Object>(3); |
| 2449 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); | 2447 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); |
| 2450 return Runtime::SetObjectProperty(isolate, | 2448 return Runtime::SetObjectProperty(isolate, |
| 2451 object, | 2449 object, |
| 2452 key, | 2450 key, |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2944 | 2942 |
| 2945 // Activate inlined smi code. | 2943 // Activate inlined smi code. |
| 2946 if (previous_state == UNINITIALIZED) { | 2944 if (previous_state == UNINITIALIZED) { |
| 2947 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); | 2945 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); |
| 2948 } | 2946 } |
| 2949 } | 2947 } |
| 2950 | 2948 |
| 2951 | 2949 |
| 2952 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. | 2950 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. |
| 2953 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { | 2951 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { |
| 2954 SealHandleScope shs(isolate); | 2952 HandleScope scope(isolate); |
| 2955 ASSERT(args.length() == 3); | 2953 ASSERT(args.length() == 3); |
| 2956 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); | 2954 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); |
| 2957 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2955 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
| 2958 return ic.target(); | 2956 return ic.raw_target(); |
| 2959 } | 2957 } |
| 2960 | 2958 |
| 2961 | 2959 |
| 2962 void CompareNilIC::Clear(Address address, Code* target) { | 2960 void CompareNilIC::Clear(Address address, Code* target) { |
| 2963 if (target->ic_state() == UNINITIALIZED) return; | 2961 if (target->ic_state() == UNINITIALIZED) return; |
| 2964 Code::ExtraICState state = target->extended_extra_ic_state(); | 2962 Code::ExtraICState state = target->extended_extra_ic_state(); |
| 2965 | 2963 |
| 2966 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); | 2964 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); |
| 2967 stub.ClearState(); | 2965 stub.ClearState(); |
| 2968 | 2966 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3052 #undef ADDR | 3050 #undef ADDR |
| 3053 }; | 3051 }; |
| 3054 | 3052 |
| 3055 | 3053 |
| 3056 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3054 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3057 return IC_utilities[id]; | 3055 return IC_utilities[id]; |
| 3058 } | 3056 } |
| 3059 | 3057 |
| 3060 | 3058 |
| 3061 } } // namespace v8::internal | 3059 } } // namespace v8::internal |
| OLD | NEW |