Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: src/ic.cc

Issue 25238002: Always cache the original target in a handle on the IC. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Return updated target Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/stub-cache.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/stub-cache.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698