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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 65 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
66 return ".IGNORE_OOB"; | 66 return ".IGNORE_OOB"; |
67 } | 67 } |
68 if (IsGrowStoreMode(mode)) return ".GROW"; | 68 if (IsGrowStoreMode(mode)) return ".GROW"; |
69 return ""; | 69 return ""; |
70 } | 70 } |
71 | 71 |
72 | 72 |
73 void IC::TraceIC(const char* type, | 73 void IC::TraceIC(const char* type, |
74 Handle<Object> name, | 74 Handle<Object> name, |
75 State old_state, | |
76 Code* new_target) { | 75 Code* new_target) { |
77 if (FLAG_trace_ic) { | 76 if (FLAG_trace_ic) { |
78 Object* undef = new_target->GetHeap()->undefined_value(); | 77 State new_state = new_target->ic_state(); |
79 State new_state = StateFrom(new_target, undef, undef); | |
80 PrintF("[%s in ", type); | 78 PrintF("[%s in ", type); |
81 Isolate* isolate = new_target->GetIsolate(); | 79 Isolate* isolate = new_target->GetIsolate(); |
82 StackFrameIterator it(isolate); | 80 StackFrameIterator it(isolate); |
83 while (it.frame()->fp() != this->fp()) it.Advance(); | 81 while (it.frame()->fp() != this->fp()) it.Advance(); |
84 StackFrame* raw_frame = it.frame(); | 82 StackFrame* raw_frame = it.frame(); |
85 if (raw_frame->is_internal()) { | 83 if (raw_frame->is_internal()) { |
86 Code* apply_builtin = isolate->builtins()->builtin( | 84 Code* apply_builtin = isolate->builtins()->builtin( |
87 Builtins::kFunctionApply); | 85 Builtins::kFunctionApply); |
88 if (raw_frame->unchecked_code() == apply_builtin) { | 86 if (raw_frame->unchecked_code() == apply_builtin) { |
89 PrintF("apply from "); | 87 PrintF("apply from "); |
90 it.Advance(); | 88 it.Advance(); |
91 raw_frame = it.frame(); | 89 raw_frame = it.frame(); |
92 } | 90 } |
93 } | 91 } |
94 JavaScriptFrame::PrintTop(isolate, stdout, false, true); | 92 JavaScriptFrame::PrintTop(isolate, stdout, false, true); |
95 Code::ExtraICState state = new_target->extra_ic_state(); | 93 Code::ExtraICState extra_state = new_target->extra_ic_state(); |
96 const char* modifier = | 94 const char* modifier = |
97 GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(state)); | 95 GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(extra_state)); |
98 PrintF(" (%c->%c%s)", | 96 PrintF(" (%c->%c%s)", |
99 TransitionMarkFromState(old_state), | 97 TransitionMarkFromState(state()), |
100 TransitionMarkFromState(new_state), | 98 TransitionMarkFromState(new_state), |
101 modifier); | 99 modifier); |
102 name->Print(); | 100 name->Print(); |
103 PrintF("]\n"); | 101 PrintF("]\n"); |
104 } | 102 } |
105 } | 103 } |
106 | 104 |
107 #define TRACE_GENERIC_IC(isolate, type, reason) \ | 105 #define TRACE_GENERIC_IC(isolate, type, reason) \ |
108 do { \ | 106 do { \ |
109 if (FLAG_trace_ic) { \ | 107 if (FLAG_trace_ic) { \ |
110 PrintF("[%s patching generic stub in ", type); \ | 108 PrintF("[%s patching generic stub in ", type); \ |
111 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ | 109 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ |
112 PrintF(" (%s)]\n", reason); \ | 110 PrintF(" (%s)]\n", reason); \ |
113 } \ | 111 } \ |
114 } while (false) | 112 } while (false) |
115 | 113 |
116 #else | 114 #else |
117 #define TRACE_GENERIC_IC(isolate, type, reason) | 115 #define TRACE_GENERIC_IC(isolate, type, reason) |
118 #endif // DEBUG | 116 #endif // DEBUG |
119 | 117 |
120 #define TRACE_IC(type, name, old_state, new_target) \ | 118 #define TRACE_IC(type, name, new_target) \ |
121 ASSERT((TraceIC(type, name, old_state, *new_target), true)) | 119 ASSERT((TraceIC(type, name, *new_target), true)) |
122 | 120 |
123 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { | 121 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { |
124 // To improve the performance of the (much used) IC code, we unfold a few | 122 // 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 | 123 // 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. | 124 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
127 const Address entry = | 125 const Address entry = |
128 Isolate::c_entry_fp(isolate->thread_local_top()); | 126 Isolate::c_entry_fp(isolate->thread_local_top()); |
129 Address* pc_address = | 127 Address* pc_address = |
130 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); | 128 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); |
131 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 129 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
132 // If there's another JavaScript frame on the stack or a | 130 // If there's another JavaScript frame on the stack or a |
133 // StubFailureTrampoline, we need to look one frame further down the stack to | 131 // StubFailureTrampoline, we need to look one frame further down the stack to |
134 // find the frame pointer and the return address stack slot. | 132 // find the frame pointer and the return address stack slot. |
135 if (depth == EXTRA_CALL_FRAME) { | 133 if (depth == EXTRA_CALL_FRAME) { |
136 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; | 134 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; |
137 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); | 135 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); |
138 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); | 136 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); |
139 } | 137 } |
140 #ifdef DEBUG | 138 #ifdef DEBUG |
141 StackFrameIterator it(isolate); | 139 StackFrameIterator it(isolate); |
142 for (int i = 0; i < depth + 1; i++) it.Advance(); | 140 for (int i = 0; i < depth + 1; i++) it.Advance(); |
143 StackFrame* frame = it.frame(); | 141 StackFrame* frame = it.frame(); |
144 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); | 142 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); |
145 #endif | 143 #endif |
146 fp_ = fp; | 144 fp_ = fp; |
147 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 145 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); |
148 target_ = handle(raw_target(), isolate); | 146 target_ = handle(raw_target(), isolate); |
| 147 state_ = target_->ic_state(); |
149 } | 148 } |
150 | 149 |
151 | 150 |
152 #ifdef ENABLE_DEBUGGER_SUPPORT | 151 #ifdef ENABLE_DEBUGGER_SUPPORT |
153 Address IC::OriginalCodeAddress() const { | 152 Address IC::OriginalCodeAddress() const { |
154 HandleScope scope(isolate()); | 153 HandleScope scope(isolate()); |
155 // Compute the JavaScript frame for the frame pointer of this IC | 154 // Compute the JavaScript frame for the frame pointer of this IC |
156 // structure. We need this to be able to find the function | 155 // structure. We need this to be able to find the function |
157 // corresponding to the frame. | 156 // corresponding to the frame. |
158 StackFrameIterator it(isolate()); | 157 StackFrameIterator it(isolate()); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 global->LocalLookupRealNamedProperty(Name::cast(name), &lookup); | 254 global->LocalLookupRealNamedProperty(Name::cast(name), &lookup); |
256 if (!lookup.IsFound()) return false; | 255 if (!lookup.IsFound()) return false; |
257 PropertyCell* cell = global->GetPropertyCell(&lookup); | 256 PropertyCell* cell = global->GetPropertyCell(&lookup); |
258 return cell->type()->IsConstant(); | 257 return cell->type()->IsConstant(); |
259 } | 258 } |
260 | 259 |
261 return false; | 260 return false; |
262 } | 261 } |
263 | 262 |
264 | 263 |
265 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { | 264 void IC::UpdateState(Object* receiver, Object* name) { |
266 IC::State state = target->ic_state(); | 265 if (state() != MONOMORPHIC || !name->IsString()) return; |
| 266 if (receiver->IsUndefined() || receiver->IsNull()) return; |
267 | 267 |
268 if (state != MONOMORPHIC || !name->IsString()) return state; | 268 Code::Kind kind = target()->kind(); |
269 if (receiver->IsUndefined() || receiver->IsNull()) return state; | |
270 | |
271 Code::Kind kind = target->kind(); | |
272 // Remove the target from the code cache if it became invalid | 269 // Remove the target from the code cache if it became invalid |
273 // because of changes in the prototype chain to avoid hitting it | 270 // because of changes in the prototype chain to avoid hitting it |
274 // again. | 271 // again. |
275 // Call stubs handle this later to allow extra IC state | 272 // Call stubs handle this later to allow extra IC state |
276 // transitions. | 273 // transitions. |
277 if (kind != Code::CALL_IC && kind != Code::KEYED_CALL_IC && | 274 if (kind != Code::CALL_IC && kind != Code::KEYED_CALL_IC && |
278 TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) { | 275 TryRemoveInvalidPrototypeDependentStub(*target_, receiver, name)) { |
279 return MONOMORPHIC_PROTOTYPE_FAILURE; | 276 MarkMonomorphicPrototypeFailure(); |
| 277 return; |
280 } | 278 } |
281 | 279 |
282 // The builtins object is special. It only changes when JavaScript | 280 // The builtins object is special. It only changes when JavaScript |
283 // builtins are loaded lazily. It is important to keep inline | 281 // builtins are loaded lazily. It is important to keep inline |
284 // caches for the builtins object monomorphic. Therefore, if we get | 282 // caches for the builtins object monomorphic. Therefore, if we get |
285 // an inline cache miss for the builtins object after lazily loading | 283 // an inline cache miss for the builtins object after lazily loading |
286 // JavaScript builtins, we return uninitialized as the state to | 284 // JavaScript builtins, we return uninitialized as the state to |
287 // force the inline cache back to monomorphic state. | 285 // force the inline cache back to monomorphic state. |
288 if (receiver->IsJSBuiltinsObject()) { | 286 if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED; |
289 return UNINITIALIZED; | |
290 } | |
291 | |
292 return MONOMORPHIC; | |
293 } | 287 } |
294 | 288 |
295 | 289 |
296 RelocInfo::Mode IC::ComputeMode() { | 290 RelocInfo::Mode IC::ComputeMode() { |
297 Address addr = address(); | 291 Address addr = address(); |
298 Code* code = Code::cast(isolate()->FindCodeObject(addr)); | 292 Code* code = Code::cast(isolate()->FindCodeObject(addr)); |
299 for (RelocIterator it(code, RelocInfo::kCodeTargetMask); | 293 for (RelocIterator it(code, RelocInfo::kCodeTargetMask); |
300 !it.done(); it.next()) { | 294 !it.done(); it.next()) { |
301 RelocInfo* info = it.rinfo(); | 295 RelocInfo* info = it.rinfo(); |
302 if (info->pc() == addr) return info->rmode(); | 296 if (info->pc() == addr) return info->rmode(); |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 // Change the receiver to the result of calling ToObject on it. | 526 // Change the receiver to the result of calling ToObject on it. |
533 const int argc = this->target()->arguments_count(); | 527 const int argc = this->target()->arguments_count(); |
534 StackFrameLocator locator(isolate()); | 528 StackFrameLocator locator(isolate()); |
535 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 529 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
536 int index = frame->ComputeExpressionsCount() - (argc + 1); | 530 int index = frame->ComputeExpressionsCount() - (argc + 1); |
537 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); | 531 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); |
538 } | 532 } |
539 } | 533 } |
540 | 534 |
541 | 535 |
542 MaybeObject* CallICBase::LoadFunction(State state, | 536 MaybeObject* CallICBase::LoadFunction(Code::ExtraICState extra_ic_state, |
543 Code::ExtraICState extra_ic_state, | |
544 Handle<Object> object, | 537 Handle<Object> object, |
545 Handle<String> name) { | 538 Handle<String> name) { |
546 bool use_ic = FLAG_use_ic; | 539 bool use_ic = FLAG_use_ic; |
547 if (object->IsJSObject()) { | 540 if (object->IsJSObject()) { |
548 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 541 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
549 if (receiver->map()->is_deprecated()) { | 542 if (receiver->map()->is_deprecated()) { |
550 use_ic = false; | 543 use_ic = false; |
551 JSObject::MigrateInstance(receiver); | 544 JSObject::MigrateInstance(receiver); |
552 } | 545 } |
553 } | 546 } |
(...skipping 25 matching lines...) Expand all Loading... |
579 | 572 |
580 if (!lookup.IsFound()) { | 573 if (!lookup.IsFound()) { |
581 // If the object does not have the requested property, check which | 574 // If the object does not have the requested property, check which |
582 // exception we need to throw. | 575 // exception we need to throw. |
583 return IsUndeclaredGlobal(object) | 576 return IsUndeclaredGlobal(object) |
584 ? ReferenceError("not_defined", name) | 577 ? ReferenceError("not_defined", name) |
585 : TypeError("undefined_method", object, name); | 578 : TypeError("undefined_method", object, name); |
586 } | 579 } |
587 | 580 |
588 // Lookup is valid: Update inline cache and stub cache. | 581 // Lookup is valid: Update inline cache and stub cache. |
589 if (use_ic) UpdateCaches(&lookup, state, extra_ic_state, object, name); | 582 if (use_ic) UpdateCaches(&lookup, extra_ic_state, object, name); |
590 | 583 |
591 // Get the property. | 584 // Get the property. |
592 PropertyAttributes attr; | 585 PropertyAttributes attr; |
593 Handle<Object> result = | 586 Handle<Object> result = |
594 Object::GetProperty(object, object, &lookup, name, &attr); | 587 Object::GetProperty(object, object, &lookup, name, &attr); |
595 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 588 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
596 | 589 |
597 if (lookup.IsInterceptor() && attr == ABSENT) { | 590 if (lookup.IsInterceptor() && attr == ABSENT) { |
598 // If the object does not have the requested property, check which | 591 // If the object does not have the requested property, check which |
599 // exception we need to throw. | 592 // exception we need to throw. |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 } | 662 } |
670 break; | 663 break; |
671 default: | 664 default: |
672 return false; | 665 return false; |
673 } | 666 } |
674 return false; | 667 return false; |
675 } | 668 } |
676 | 669 |
677 | 670 |
678 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, | 671 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, |
679 State state, | |
680 Code::ExtraICState extra_state, | 672 Code::ExtraICState extra_state, |
681 Handle<Object> object, | 673 Handle<Object> object, |
682 Handle<String> name) { | 674 Handle<String> name) { |
683 int argc = target()->arguments_count(); | 675 int argc = target()->arguments_count(); |
684 Handle<JSObject> holder(lookup->holder(), isolate()); | 676 Handle<JSObject> holder(lookup->holder(), isolate()); |
685 switch (lookup->type()) { | 677 switch (lookup->type()) { |
686 case FIELD: { | 678 case FIELD: { |
687 PropertyIndex index = lookup->GetFieldIndex(); | 679 PropertyIndex index = lookup->GetFieldIndex(); |
688 return isolate()->stub_cache()->ComputeCallField( | 680 return isolate()->stub_cache()->ComputeCallField( |
689 argc, kind_, extra_state, name, object, holder, index); | 681 argc, kind_, extra_state, name, object, holder, index); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 ASSERT(HasInterceptorGetter(*holder)); | 717 ASSERT(HasInterceptorGetter(*holder)); |
726 return isolate()->stub_cache()->ComputeCallInterceptor( | 718 return isolate()->stub_cache()->ComputeCallInterceptor( |
727 argc, kind_, extra_state, name, object, holder); | 719 argc, kind_, extra_state, name, object, holder); |
728 default: | 720 default: |
729 return Handle<Code>::null(); | 721 return Handle<Code>::null(); |
730 } | 722 } |
731 } | 723 } |
732 | 724 |
733 | 725 |
734 void CallICBase::UpdateCaches(LookupResult* lookup, | 726 void CallICBase::UpdateCaches(LookupResult* lookup, |
735 State state, | |
736 Code::ExtraICState extra_ic_state, | 727 Code::ExtraICState extra_ic_state, |
737 Handle<Object> object, | 728 Handle<Object> object, |
738 Handle<String> name) { | 729 Handle<String> name) { |
739 // Bail out if we didn't find a result. | 730 // Bail out if we didn't find a result. |
740 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 731 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
741 | 732 |
742 // Compute the number of arguments. | 733 // Compute the number of arguments. |
743 int argc = target()->arguments_count(); | 734 int argc = target()->arguments_count(); |
744 Handle<Code> code; | 735 Handle<Code> code; |
745 if (state == UNINITIALIZED) { | 736 if (state() == UNINITIALIZED) { |
746 // This is the first time we execute this inline cache. | 737 // This is the first time we execute this inline cache. |
747 // Set the target to the pre monomorphic stub to delay | 738 // Set the target to the pre monomorphic stub to delay |
748 // setting the monomorphic state. | 739 // setting the monomorphic state. |
749 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( | 740 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( |
750 argc, kind_, extra_ic_state); | 741 argc, kind_, extra_ic_state); |
751 } else if (state == MONOMORPHIC) { | 742 } else if (state() == MONOMORPHIC) { |
752 if (kind_ == Code::CALL_IC && | 743 if (kind_ == Code::CALL_IC && |
753 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 744 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { |
754 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, | 745 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name); |
755 object, name); | |
756 } else if (TryRemoveInvalidPrototypeDependentStub(*target(), | 746 } else if (TryRemoveInvalidPrototypeDependentStub(*target(), |
757 *object, | 747 *object, |
758 *name)) { | 748 *name)) { |
759 state = MONOMORPHIC_PROTOTYPE_FAILURE; | 749 MarkMonomorphicPrototypeFailure(); |
760 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, | 750 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name); |
761 object, name); | |
762 } else { | 751 } else { |
763 code = isolate()->stub_cache()->ComputeCallMegamorphic( | 752 code = isolate()->stub_cache()->ComputeCallMegamorphic( |
764 argc, kind_, extra_ic_state); | 753 argc, kind_, extra_ic_state); |
765 } | 754 } |
766 } else { | 755 } else { |
767 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, | 756 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name); |
768 object, name); | |
769 } | 757 } |
770 | 758 |
771 // If there's no appropriate stub we simply avoid updating the caches. | 759 // If there's no appropriate stub we simply avoid updating the caches. |
772 if (code.is_null()) return; | 760 if (code.is_null()) return; |
773 | 761 |
774 // Patch the call site depending on the state of the cache. | 762 // Patch the call site depending on the state of the cache. |
775 switch (state) { | 763 switch (state()) { |
776 case UNINITIALIZED: | 764 case UNINITIALIZED: |
777 case MONOMORPHIC_PROTOTYPE_FAILURE: | 765 case MONOMORPHIC_PROTOTYPE_FAILURE: |
778 case PREMONOMORPHIC: | 766 case PREMONOMORPHIC: |
779 case MONOMORPHIC: | 767 case MONOMORPHIC: |
780 set_target(*code); | 768 set_target(*code); |
781 break; | 769 break; |
782 case MEGAMORPHIC: { | 770 case MEGAMORPHIC: { |
783 // Cache code holding map should be consistent with | 771 // Cache code holding map should be consistent with |
784 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. | 772 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. |
785 Handle<JSObject> cache_object = object->IsJSObject() | 773 Handle<JSObject> cache_object = object->IsJSObject() |
786 ? Handle<JSObject>::cast(object) | 774 ? Handle<JSObject>::cast(object) |
787 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), | 775 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), |
788 isolate()); | 776 isolate()); |
789 // Update the stub cache. | 777 // Update the stub cache. |
790 UpdateMegamorphicCache(cache_object->map(), *name, *code); | 778 UpdateMegamorphicCache(cache_object->map(), *name, *code); |
791 break; | 779 break; |
792 } | 780 } |
793 case DEBUG_STUB: | 781 case DEBUG_STUB: |
794 break; | 782 break; |
795 case POLYMORPHIC: | 783 case POLYMORPHIC: |
796 case GENERIC: | 784 case GENERIC: |
797 UNREACHABLE(); | 785 UNREACHABLE(); |
798 break; | 786 break; |
799 } | 787 } |
800 | 788 |
801 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 789 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", name, target()); |
802 name, state, target()); | |
803 } | 790 } |
804 | 791 |
805 | 792 |
806 MaybeObject* KeyedCallIC::LoadFunction(State state, | 793 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, |
807 Handle<Object> object, | |
808 Handle<Object> key) { | 794 Handle<Object> key) { |
809 if (key->IsInternalizedString()) { | 795 if (key->IsInternalizedString()) { |
810 return CallICBase::LoadFunction(state, | 796 return CallICBase::LoadFunction(Code::kNoExtraICState, |
811 Code::kNoExtraICState, | |
812 object, | 797 object, |
813 Handle<String>::cast(key)); | 798 Handle<String>::cast(key)); |
814 } | 799 } |
815 | 800 |
816 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 801 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
817 if (object->IsJSObject()) { | 802 if (object->IsJSObject()) { |
818 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 803 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
819 if (receiver->map()->is_deprecated()) { | 804 if (receiver->map()->is_deprecated()) { |
820 use_ic = false; | 805 use_ic = false; |
821 JSObject::MigrateInstance(receiver); | 806 JSObject::MigrateInstance(receiver); |
822 } | 807 } |
823 } | 808 } |
824 | 809 |
825 if (object->IsUndefined() || object->IsNull()) { | 810 if (object->IsUndefined() || object->IsNull()) { |
826 return TypeError("non_object_property_call", object, key); | 811 return TypeError("non_object_property_call", object, key); |
827 } | 812 } |
828 | 813 |
829 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 814 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
830 | 815 |
831 if (use_ic && state != MEGAMORPHIC) { | 816 if (use_ic && state() != MEGAMORPHIC) { |
832 int argc = target()->arguments_count(); | 817 int argc = target()->arguments_count(); |
833 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( | 818 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( |
834 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 819 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
835 if (object->IsJSObject()) { | 820 if (object->IsJSObject()) { |
836 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 821 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
837 if (receiver->elements()->map() == | 822 if (receiver->elements()->map() == |
838 isolate()->heap()->non_strict_arguments_elements_map()) { | 823 isolate()->heap()->non_strict_arguments_elements_map()) { |
839 stub = isolate()->stub_cache()->ComputeCallArguments(argc); | 824 stub = isolate()->stub_cache()->ComputeCallArguments(argc); |
840 } | 825 } |
841 } | 826 } |
842 ASSERT(!stub.is_null()); | 827 ASSERT(!stub.is_null()); |
843 set_target(*stub); | 828 set_target(*stub); |
844 TRACE_IC("KeyedCallIC", key, state, target()); | 829 TRACE_IC("KeyedCallIC", key, target()); |
845 } | 830 } |
846 | 831 |
847 Handle<Object> result = GetProperty(isolate(), object, key); | 832 Handle<Object> result = GetProperty(isolate(), object, key); |
848 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 833 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
849 | 834 |
850 // Make receiver an object if the callee requires it. Strict mode or builtin | 835 // Make receiver an object if the callee requires it. Strict mode or builtin |
851 // functions do not wrap the receiver, non-strict functions and objects | 836 // functions do not wrap the receiver, non-strict functions and objects |
852 // called as functions do. | 837 // called as functions do. |
853 ReceiverToObjectIfRequired(result, object); | 838 ReceiverToObjectIfRequired(result, object); |
854 if (result->IsJSFunction()) return *result; | 839 if (result->IsJSFunction()) return *result; |
855 | 840 |
856 result = TryCallAsFunction(result); | 841 result = TryCallAsFunction(result); |
857 if (result->IsJSFunction()) return *result; | 842 if (result->IsJSFunction()) return *result; |
858 | 843 |
859 return TypeError("property_not_function", object, key); | 844 return TypeError("property_not_function", object, key); |
860 } | 845 } |
861 | 846 |
862 | 847 |
863 MaybeObject* LoadIC::Load(State state, | 848 MaybeObject* LoadIC::Load(Handle<Object> object, |
864 Handle<Object> object, | |
865 Handle<String> name) { | 849 Handle<String> name) { |
866 // If the object is undefined or null it's illegal to try to get any | 850 // If the object is undefined or null it's illegal to try to get any |
867 // of its properties; throw a TypeError in that case. | 851 // of its properties; throw a TypeError in that case. |
868 if (object->IsUndefined() || object->IsNull()) { | 852 if (object->IsUndefined() || object->IsNull()) { |
869 return TypeError("non_object_property_load", object, name); | 853 return TypeError("non_object_property_load", object, name); |
870 } | 854 } |
871 | 855 |
872 bool use_ic = FLAG_use_ic; | 856 bool use_ic = FLAG_use_ic; |
873 | 857 |
874 if (use_ic) { | 858 if (use_ic) { |
875 // Use specialized code for getting the length of strings and | 859 // Use specialized code for getting the length of strings and |
876 // string wrapper objects. The length property of string wrapper | 860 // string wrapper objects. The length property of string wrapper |
877 // objects is read-only and therefore always returns the length of | 861 // objects is read-only and therefore always returns the length of |
878 // the underlying string value. See ECMA-262 15.5.5.1. | 862 // the underlying string value. See ECMA-262 15.5.5.1. |
879 if (object->IsStringWrapper() && | 863 if (object->IsStringWrapper() && |
880 name->Equals(isolate()->heap()->length_string())) { | 864 name->Equals(isolate()->heap()->length_string())) { |
881 Handle<Code> stub; | 865 Handle<Code> stub; |
882 if (state == UNINITIALIZED) { | 866 if (state() == UNINITIALIZED) { |
883 stub = pre_monomorphic_stub(); | 867 stub = pre_monomorphic_stub(); |
884 } else if (state == PREMONOMORPHIC || state == MONOMORPHIC) { | 868 } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) { |
885 StringLengthStub string_length_stub(kind()); | 869 StringLengthStub string_length_stub(kind()); |
886 stub = string_length_stub.GetCode(isolate()); | 870 stub = string_length_stub.GetCode(isolate()); |
887 } else if (state != MEGAMORPHIC) { | 871 } else if (state() != MEGAMORPHIC) { |
888 ASSERT(state != GENERIC); | 872 ASSERT(state() != GENERIC); |
889 stub = megamorphic_stub(); | 873 stub = megamorphic_stub(); |
890 } | 874 } |
891 if (!stub.is_null()) { | 875 if (!stub.is_null()) { |
892 set_target(*stub); | 876 set_target(*stub); |
893 #ifdef DEBUG | 877 #ifdef DEBUG |
894 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); | 878 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); |
895 #endif | 879 #endif |
896 } | 880 } |
897 // Get the string if we have a string wrapper object. | 881 // Get the string if we have a string wrapper object. |
898 String* string = String::cast(JSValue::cast(*object)->value()); | 882 String* string = String::cast(JSValue::cast(*object)->value()); |
899 return Smi::FromInt(string->length()); | 883 return Smi::FromInt(string->length()); |
900 } | 884 } |
901 | 885 |
902 // Use specialized code for getting prototype of functions. | 886 // Use specialized code for getting prototype of functions. |
903 if (object->IsJSFunction() && | 887 if (object->IsJSFunction() && |
904 name->Equals(isolate()->heap()->prototype_string()) && | 888 name->Equals(isolate()->heap()->prototype_string()) && |
905 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 889 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
906 Handle<Code> stub; | 890 Handle<Code> stub; |
907 if (state == UNINITIALIZED) { | 891 if (state() == UNINITIALIZED) { |
908 stub = pre_monomorphic_stub(); | 892 stub = pre_monomorphic_stub(); |
909 } else if (state == PREMONOMORPHIC) { | 893 } else if (state() == PREMONOMORPHIC) { |
910 FunctionPrototypeStub function_prototype_stub(kind()); | 894 FunctionPrototypeStub function_prototype_stub(kind()); |
911 stub = function_prototype_stub.GetCode(isolate()); | 895 stub = function_prototype_stub.GetCode(isolate()); |
912 } else if (state != MEGAMORPHIC) { | 896 } else if (state() != MEGAMORPHIC) { |
913 ASSERT(state != GENERIC); | 897 ASSERT(state() != GENERIC); |
914 stub = megamorphic_stub(); | 898 stub = megamorphic_stub(); |
915 } | 899 } |
916 if (!stub.is_null()) { | 900 if (!stub.is_null()) { |
917 set_target(*stub); | 901 set_target(*stub); |
918 #ifdef DEBUG | 902 #ifdef DEBUG |
919 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 903 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); |
920 #endif | 904 #endif |
921 } | 905 } |
922 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); | 906 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); |
923 } | 907 } |
(...skipping 22 matching lines...) Expand all Loading... |
946 | 930 |
947 // If we did not find a property, check if we need to throw an exception. | 931 // If we did not find a property, check if we need to throw an exception. |
948 if (!lookup.IsFound()) { | 932 if (!lookup.IsFound()) { |
949 if (IsUndeclaredGlobal(object)) { | 933 if (IsUndeclaredGlobal(object)) { |
950 return ReferenceError("not_defined", name); | 934 return ReferenceError("not_defined", name); |
951 } | 935 } |
952 LOG(isolate(), SuspectReadEvent(*name, *object)); | 936 LOG(isolate(), SuspectReadEvent(*name, *object)); |
953 } | 937 } |
954 | 938 |
955 // Update inline cache and stub cache. | 939 // Update inline cache and stub cache. |
956 if (use_ic) UpdateCaches(&lookup, state, object, name); | 940 if (use_ic) UpdateCaches(&lookup, object, name); |
957 | 941 |
958 PropertyAttributes attr; | 942 PropertyAttributes attr; |
959 if (lookup.IsInterceptor() || lookup.IsHandler()) { | 943 if (lookup.IsInterceptor() || lookup.IsHandler()) { |
960 // Get the property. | 944 // Get the property. |
961 Handle<Object> result = | 945 Handle<Object> result = |
962 Object::GetProperty(object, object, &lookup, name, &attr); | 946 Object::GetProperty(object, object, &lookup, name, &attr); |
963 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 947 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
964 // If the property is not present, check if we need to throw an | 948 // If the property is not present, check if we need to throw an |
965 // exception. | 949 // exception. |
966 if (attr == ABSENT && IsUndeclaredGlobal(object)) { | 950 if (attr == ABSENT && IsUndeclaredGlobal(object)) { |
(...skipping 14 matching lines...) Expand all Loading... |
981 if (!receiver_maps->at(current).is_null() && | 965 if (!receiver_maps->at(current).is_null() && |
982 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 966 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
983 return false; | 967 return false; |
984 } | 968 } |
985 } | 969 } |
986 receiver_maps->Add(new_receiver_map); | 970 receiver_maps->Add(new_receiver_map); |
987 return true; | 971 return true; |
988 } | 972 } |
989 | 973 |
990 | 974 |
991 bool IC::UpdatePolymorphicIC(State state, | 975 bool IC::UpdatePolymorphicIC(Handle<HeapObject> receiver, |
992 Handle<HeapObject> receiver, | |
993 Handle<String> name, | 976 Handle<String> name, |
994 Handle<Code> code) { | 977 Handle<Code> code) { |
995 if (!code->is_handler()) return false; | 978 if (!code->is_handler()) return false; |
996 | 979 |
997 MapHandleList receiver_maps; | 980 MapHandleList receiver_maps; |
998 CodeHandleList handlers; | 981 CodeHandleList handlers; |
999 | 982 |
1000 int number_of_valid_maps; | 983 int number_of_valid_maps; |
1001 int handler_to_overwrite = -1; | 984 int handler_to_overwrite = -1; |
1002 Handle<Map> new_receiver_map(receiver->map()); | 985 Handle<Map> new_receiver_map(receiver->map()); |
(...skipping 11 matching lines...) Expand all Loading... |
1014 // If the receiver map is already in the polymorphic IC, this indicates | 997 // If the receiver map is already in the polymorphic IC, this indicates |
1015 // there was a prototoype chain failure. In that case, just overwrite the | 998 // there was a prototoype chain failure. In that case, just overwrite the |
1016 // handler. | 999 // handler. |
1017 } else if (map.is_identical_to(new_receiver_map)) { | 1000 } else if (map.is_identical_to(new_receiver_map)) { |
1018 number_of_valid_maps--; | 1001 number_of_valid_maps--; |
1019 handler_to_overwrite = i; | 1002 handler_to_overwrite = i; |
1020 } | 1003 } |
1021 } | 1004 } |
1022 | 1005 |
1023 if (number_of_valid_maps >= 4) return false; | 1006 if (number_of_valid_maps >= 4) return false; |
1024 | 1007 if (number_of_maps == 0) return false; |
1025 // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC. | |
1026 // In that case, allow the IC to go back monomorphic. | |
1027 if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) { | |
1028 return false; | |
1029 } | |
1030 | 1008 |
1031 if (!target()->FindHandlers(&handlers, receiver_maps.length())) { | 1009 if (!target()->FindHandlers(&handlers, receiver_maps.length())) { |
1032 return false; | 1010 return false; |
1033 } | 1011 } |
1034 } | 1012 } |
1035 | 1013 |
1036 number_of_valid_maps++; | 1014 number_of_valid_maps++; |
1037 if (handler_to_overwrite >= 0) { | 1015 if (handler_to_overwrite >= 0) { |
1038 handlers.Set(handler_to_overwrite, code); | 1016 handlers.Set(handler_to_overwrite, code); |
1039 } else { | 1017 } else { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1081 IsMoreGeneralElementsKindTransition( | 1059 IsMoreGeneralElementsKindTransition( |
1082 current_map->elements_kind(), receiver_elements_kind); | 1060 current_map->elements_kind(), receiver_elements_kind); |
1083 Map* transitioned_map = more_general_transition | 1061 Map* transitioned_map = more_general_transition |
1084 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) | 1062 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) |
1085 : NULL; | 1063 : NULL; |
1086 | 1064 |
1087 return transitioned_map == receiver_map; | 1065 return transitioned_map == receiver_map; |
1088 } | 1066 } |
1089 | 1067 |
1090 | 1068 |
1091 void IC::PatchCache(State state, | 1069 void IC::PatchCache(Handle<HeapObject> receiver, |
1092 Handle<HeapObject> receiver, | |
1093 Handle<String> name, | 1070 Handle<String> name, |
1094 Handle<Code> code) { | 1071 Handle<Code> code) { |
1095 switch (state) { | 1072 switch (state()) { |
1096 case UNINITIALIZED: | 1073 case UNINITIALIZED: |
1097 case PREMONOMORPHIC: | 1074 case PREMONOMORPHIC: |
1098 case MONOMORPHIC_PROTOTYPE_FAILURE: | 1075 case MONOMORPHIC_PROTOTYPE_FAILURE: |
1099 UpdateMonomorphicIC(receiver, code, name); | 1076 UpdateMonomorphicIC(receiver, code, name); |
1100 break; | 1077 break; |
1101 case MONOMORPHIC: | 1078 case MONOMORPHIC: |
1102 ASSERT(!target().is_identical_to(code)); | 1079 ASSERT(!target().is_identical_to(code)); |
1103 if (!target()->is_keyed_stub()) { | 1080 if (!target()->is_keyed_stub()) { |
1104 bool is_same_handler = false; | 1081 bool is_same_handler = false; |
1105 { | 1082 { |
1106 DisallowHeapAllocation no_allocation; | 1083 DisallowHeapAllocation no_allocation; |
1107 Code* old_handler = target()->FindFirstHandler(); | 1084 Code* old_handler = target()->FindFirstHandler(); |
1108 is_same_handler = old_handler == *code; | 1085 is_same_handler = old_handler == *code; |
1109 } | 1086 } |
1110 if (is_same_handler | 1087 if (is_same_handler |
1111 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { | 1088 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { |
1112 UpdateMonomorphicIC(receiver, code, name); | 1089 UpdateMonomorphicIC(receiver, code, name); |
1113 break; | 1090 break; |
1114 } | 1091 } |
1115 if (UpdatePolymorphicIC(state, receiver, name, code)) { | 1092 if (UpdatePolymorphicIC(receiver, name, code)) { |
1116 break; | 1093 break; |
1117 } | 1094 } |
1118 | 1095 |
1119 CopyICToMegamorphicCache(name); | 1096 CopyICToMegamorphicCache(name); |
1120 } | 1097 } |
1121 | 1098 |
1122 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1099 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1123 set_target(*megamorphic_stub()); | 1100 set_target(*megamorphic_stub()); |
1124 break; | 1101 break; |
1125 case MEGAMORPHIC: | 1102 case MEGAMORPHIC: |
1126 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1103 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1127 break; | 1104 break; |
1128 case POLYMORPHIC: | 1105 case POLYMORPHIC: |
1129 if (target()->is_keyed_stub()) { | 1106 if (target()->is_keyed_stub()) { |
1130 // When trying to patch a polymorphic keyed stub with anything other | 1107 // When trying to patch a polymorphic keyed stub with anything other |
1131 // than another polymorphic stub, go generic. | 1108 // than another polymorphic stub, go generic. |
1132 set_target(*generic_stub()); | 1109 set_target(*generic_stub()); |
1133 } else { | 1110 } else { |
1134 if (UpdatePolymorphicIC(state, receiver, name, code)) { | 1111 if (UpdatePolymorphicIC(receiver, name, code)) { |
1135 break; | 1112 break; |
1136 } | 1113 } |
1137 CopyICToMegamorphicCache(name); | 1114 CopyICToMegamorphicCache(name); |
1138 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1115 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1139 set_target(*megamorphic_stub()); | 1116 set_target(*megamorphic_stub()); |
1140 } | 1117 } |
1141 break; | 1118 break; |
1142 case DEBUG_STUB: | 1119 case DEBUG_STUB: |
1143 break; | 1120 break; |
1144 case GENERIC: | 1121 case GENERIC: |
1145 UNREACHABLE(); | 1122 UNREACHABLE(); |
1146 break; | 1123 break; |
1147 } | 1124 } |
1148 } | 1125 } |
1149 | 1126 |
1150 | 1127 |
1151 static void GetReceiverMapsForStub(Handle<Code> stub, | |
1152 MapHandleList* result) { | |
1153 ASSERT(stub->is_inline_cache_stub()); | |
1154 switch (stub->ic_state()) { | |
1155 case MONOMORPHIC: { | |
1156 Map* map = stub->FindFirstMap(); | |
1157 if (map != NULL) { | |
1158 result->Add(Handle<Map>(map)); | |
1159 } | |
1160 break; | |
1161 } | |
1162 case POLYMORPHIC: { | |
1163 DisallowHeapAllocation no_allocation; | |
1164 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | |
1165 for (RelocIterator it(*stub, mask); !it.done(); it.next()) { | |
1166 RelocInfo* info = it.rinfo(); | |
1167 Handle<Object> object(info->target_object(), stub->GetIsolate()); | |
1168 if (object->IsString()) break; | |
1169 ASSERT(object->IsMap()); | |
1170 AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object)); | |
1171 } | |
1172 break; | |
1173 } | |
1174 case MEGAMORPHIC: | |
1175 break; | |
1176 case UNINITIALIZED: | |
1177 case PREMONOMORPHIC: | |
1178 case MONOMORPHIC_PROTOTYPE_FAILURE: | |
1179 case GENERIC: | |
1180 case DEBUG_STUB: | |
1181 UNREACHABLE(); | |
1182 break; | |
1183 } | |
1184 } | |
1185 | |
1186 | |
1187 void LoadIC::UpdateCaches(LookupResult* lookup, | 1128 void LoadIC::UpdateCaches(LookupResult* lookup, |
1188 State state, | |
1189 Handle<Object> object, | 1129 Handle<Object> object, |
1190 Handle<String> name) { | 1130 Handle<String> name) { |
1191 // TODO(verwaest): It would be nice to support loading fields from smis as | 1131 // TODO(verwaest): It would be nice to support loading fields from smis as |
1192 // well. For now just fail to update the cache. | 1132 // well. For now just fail to update the cache. |
1193 if (!object->IsHeapObject()) return; | 1133 if (!object->IsHeapObject()) return; |
1194 | 1134 |
1195 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); | 1135 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
1196 | 1136 |
1197 Handle<Code> code; | 1137 Handle<Code> code; |
1198 if (state == UNINITIALIZED) { | 1138 if (state() == UNINITIALIZED) { |
1199 // This is the first time we execute this inline cache. | 1139 // This is the first time we execute this inline cache. |
1200 // Set the target to the pre monomorphic stub to delay | 1140 // Set the target to the pre monomorphic stub to delay |
1201 // setting the monomorphic state. | 1141 // setting the monomorphic state. |
1202 code = pre_monomorphic_stub(); | 1142 code = pre_monomorphic_stub(); |
1203 } else if (!lookup->IsCacheable()) { | 1143 } else if (!lookup->IsCacheable()) { |
1204 // Bail out if the result is not cacheable. | 1144 // Bail out if the result is not cacheable. |
1205 code = slow_stub(); | 1145 code = slow_stub(); |
1206 } else if (object->IsString() && | 1146 } else if (object->IsString() && |
1207 name->Equals(isolate()->heap()->length_string())) { | 1147 name->Equals(isolate()->heap()->length_string())) { |
1208 int length_index = String::kLengthOffset / kPointerSize; | 1148 int length_index = String::kLengthOffset / kPointerSize; |
1209 if (target()->is_load_stub()) { | 1149 if (target()->is_load_stub()) { |
1210 LoadFieldStub stub(true, length_index, Representation::Tagged()); | 1150 LoadFieldStub stub(true, length_index, Representation::Tagged()); |
1211 code = stub.GetCode(isolate()); | 1151 code = stub.GetCode(isolate()); |
1212 } else { | 1152 } else { |
1213 KeyedLoadFieldStub stub(true, length_index, Representation::Tagged()); | 1153 KeyedLoadFieldStub stub(true, length_index, Representation::Tagged()); |
1214 code = stub.GetCode(isolate()); | 1154 code = stub.GetCode(isolate()); |
1215 } | 1155 } |
1216 } else if (!object->IsJSObject()) { | 1156 } else if (!object->IsJSObject()) { |
1217 // TODO(jkummerow): It would be nice to support non-JSObjects in | 1157 // TODO(jkummerow): It would be nice to support non-JSObjects in |
1218 // ComputeLoadHandler, then we wouldn't need to go generic here. | 1158 // ComputeLoadHandler, then we wouldn't need to go generic here. |
1219 code = slow_stub(); | 1159 code = slow_stub(); |
1220 } else { | 1160 } else { |
1221 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name); | 1161 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name); |
1222 if (code.is_null()) code = slow_stub(); | 1162 if (code.is_null()) code = slow_stub(); |
1223 } | 1163 } |
1224 | 1164 |
1225 PatchCache(state, receiver, name, code); | 1165 PatchCache(receiver, name, code); |
1226 TRACE_IC("LoadIC", name, state, target()); | 1166 TRACE_IC("LoadIC", name, target()); |
1227 } | 1167 } |
1228 | 1168 |
1229 | 1169 |
1230 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { | 1170 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { |
1231 // Cache code holding map should be consistent with | 1171 // Cache code holding map should be consistent with |
1232 // GenerateMonomorphicCacheProbe. | 1172 // GenerateMonomorphicCacheProbe. |
1233 isolate()->stub_cache()->Set(name, map, code); | 1173 isolate()->stub_cache()->Set(name, map, code); |
1234 } | 1174 } |
1235 | 1175 |
1236 | 1176 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1339 } | 1279 } |
1340 } | 1280 } |
1341 } else if (key->IsUndefined()) { | 1281 } else if (key->IsUndefined()) { |
1342 key = isolate->factory()->undefined_string(); | 1282 key = isolate->factory()->undefined_string(); |
1343 } | 1283 } |
1344 return key; | 1284 return key; |
1345 } | 1285 } |
1346 | 1286 |
1347 | 1287 |
1348 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { | 1288 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { |
1349 State ic_state = target()->ic_state(); | |
1350 | |
1351 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1289 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
1352 // via megamorphic stubs, since they don't have a map in their relocation info | 1290 // via megamorphic stubs, since they don't have a map in their relocation info |
1353 // and so the stubs can't be harvested for the object needed for a map check. | 1291 // and so the stubs can't be harvested for the object needed for a map check. |
1354 if (target()->type() != Code::NORMAL) { | 1292 if (target()->type() != Code::NORMAL) { |
1355 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); | 1293 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); |
1356 return generic_stub(); | 1294 return generic_stub(); |
1357 } | 1295 } |
1358 | 1296 |
1359 Handle<Map> receiver_map(receiver->map(), isolate()); | 1297 Handle<Map> receiver_map(receiver->map(), isolate()); |
1360 MapHandleList target_receiver_maps; | 1298 MapHandleList target_receiver_maps; |
1361 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { | 1299 if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) { |
1362 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1300 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state |
1363 // yet will do so and stay there. | 1301 // yet will do so and stay there. |
1364 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1302 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
1365 } | 1303 } |
1366 | 1304 |
1367 if (target().is_identical_to(string_stub())) { | 1305 if (target().is_identical_to(string_stub())) { |
1368 target_receiver_maps.Add(isolate()->factory()->string_map()); | 1306 target_receiver_maps.Add(isolate()->factory()->string_map()); |
1369 } else { | 1307 } else { |
1370 GetReceiverMapsForStub(target(), &target_receiver_maps); | 1308 target()->FindAllMaps(&target_receiver_maps); |
1371 if (target_receiver_maps.length() == 0) { | 1309 if (target_receiver_maps.length() == 0) { |
1372 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1310 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
1373 } | 1311 } |
1374 } | 1312 } |
1375 | 1313 |
1376 // The first time a receiver is seen that is a transitioned version of the | 1314 // The first time a receiver is seen that is a transitioned version of the |
1377 // previous monomorphic receiver type, assume the new ElementsKind is the | 1315 // previous monomorphic receiver type, assume the new ElementsKind is the |
1378 // monomorphic type. This benefits global arrays that only transition | 1316 // monomorphic type. This benefits global arrays that only transition |
1379 // once, and all call sites accessing them are faster if they remain | 1317 // once, and all call sites accessing them are faster if they remain |
1380 // monomorphic. If this optimistic assumption is not true, the IC will | 1318 // monomorphic. If this optimistic assumption is not true, the IC will |
1381 // miss again and it will become polymorphic and support both the | 1319 // miss again and it will become polymorphic and support both the |
1382 // untransitioned and transitioned maps. | 1320 // untransitioned and transitioned maps. |
1383 if (ic_state == MONOMORPHIC && | 1321 if (state() == MONOMORPHIC && |
1384 IsMoreGeneralElementsKindTransition( | 1322 IsMoreGeneralElementsKindTransition( |
1385 target_receiver_maps.at(0)->elements_kind(), | 1323 target_receiver_maps.at(0)->elements_kind(), |
1386 receiver->GetElementsKind())) { | 1324 receiver->GetElementsKind())) { |
1387 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1325 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
1388 } | 1326 } |
1389 | 1327 |
1390 ASSERT(ic_state != GENERIC); | 1328 ASSERT(state() != GENERIC); |
1391 | 1329 |
1392 // Determine the list of receiver maps that this call site has seen, | 1330 // Determine the list of receiver maps that this call site has seen, |
1393 // adding the map that was just encountered. | 1331 // adding the map that was just encountered. |
1394 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1332 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
1395 // If the miss wasn't due to an unseen map, a polymorphic stub | 1333 // If the miss wasn't due to an unseen map, a polymorphic stub |
1396 // won't help, use the generic stub. | 1334 // won't help, use the generic stub. |
1397 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); | 1335 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); |
1398 return generic_stub(); | 1336 return generic_stub(); |
1399 } | 1337 } |
1400 | 1338 |
1401 // If the maximum number of receiver maps has been exceeded, use the generic | 1339 // If the maximum number of receiver maps has been exceeded, use the generic |
1402 // version of the IC. | 1340 // version of the IC. |
1403 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1341 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
1404 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); | 1342 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); |
1405 return generic_stub(); | 1343 return generic_stub(); |
1406 } | 1344 } |
1407 | 1345 |
1408 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( | 1346 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( |
1409 &target_receiver_maps); | 1347 &target_receiver_maps); |
1410 } | 1348 } |
1411 | 1349 |
1412 | 1350 |
1413 MaybeObject* KeyedLoadIC::Load(State state, | 1351 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, |
1414 Handle<Object> object, | |
1415 Handle<Object> key, | 1352 Handle<Object> key, |
1416 ICMissMode miss_mode) { | 1353 ICMissMode miss_mode) { |
1417 // Check for values that can be converted into an internalized string directly | 1354 // Check for values that can be converted into an internalized string directly |
1418 // or is representable as a smi. | 1355 // or is representable as a smi. |
1419 key = TryConvertKey(key, isolate()); | 1356 key = TryConvertKey(key, isolate()); |
1420 | 1357 |
1421 if (key->IsInternalizedString()) { | 1358 if (key->IsInternalizedString()) { |
1422 return LoadIC::Load(state, object, Handle<String>::cast(key)); | 1359 return LoadIC::Load(object, Handle<String>::cast(key)); |
1423 } | 1360 } |
1424 | 1361 |
1425 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1362 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
1426 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1363 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
1427 | 1364 |
1428 if (use_ic) { | 1365 if (use_ic) { |
1429 Handle<Code> stub = generic_stub(); | 1366 Handle<Code> stub = generic_stub(); |
1430 if (miss_mode != MISS_FORCE_GENERIC) { | 1367 if (miss_mode != MISS_FORCE_GENERIC) { |
1431 if (object->IsString() && key->IsNumber()) { | 1368 if (object->IsString() && key->IsNumber()) { |
1432 if (state == UNINITIALIZED) { | 1369 if (state() == UNINITIALIZED) { |
1433 stub = string_stub(); | 1370 stub = string_stub(); |
1434 } | 1371 } |
1435 } else if (object->IsJSObject()) { | 1372 } else if (object->IsJSObject()) { |
1436 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1373 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1437 if (receiver->map()->is_deprecated()) { | 1374 if (receiver->map()->is_deprecated()) { |
1438 use_ic = false; | 1375 use_ic = false; |
1439 JSObject::MigrateInstance(receiver); | 1376 JSObject::MigrateInstance(receiver); |
1440 } | 1377 } |
1441 | 1378 |
1442 if (receiver->elements()->map() == | 1379 if (receiver->elements()->map() == |
1443 isolate()->heap()->non_strict_arguments_elements_map()) { | 1380 isolate()->heap()->non_strict_arguments_elements_map()) { |
1444 stub = non_strict_arguments_stub(); | 1381 stub = non_strict_arguments_stub(); |
1445 } else if (receiver->HasIndexedInterceptor()) { | 1382 } else if (receiver->HasIndexedInterceptor()) { |
1446 stub = indexed_interceptor_stub(); | 1383 stub = indexed_interceptor_stub(); |
1447 } else if (!key->ToSmi()->IsFailure() && | 1384 } else if (!key->ToSmi()->IsFailure() && |
1448 (!target().is_identical_to(non_strict_arguments_stub()))) { | 1385 (!target().is_identical_to(non_strict_arguments_stub()))) { |
1449 stub = LoadElementStub(receiver); | 1386 stub = LoadElementStub(receiver); |
1450 } | 1387 } |
1451 } | 1388 } |
1452 } else { | 1389 } else { |
1453 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); | 1390 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); |
1454 } | 1391 } |
1455 if (use_ic) { | 1392 if (use_ic) { |
1456 ASSERT(!stub.is_null()); | 1393 ASSERT(!stub.is_null()); |
1457 set_target(*stub); | 1394 set_target(*stub); |
1458 TRACE_IC("KeyedLoadIC", key, state, target()); | 1395 TRACE_IC("KeyedLoadIC", key, target()); |
1459 } | 1396 } |
1460 } | 1397 } |
1461 | 1398 |
1462 | 1399 |
1463 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | 1400 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
1464 } | 1401 } |
1465 | 1402 |
1466 | 1403 |
1467 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, | 1404 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, |
1468 Handle<JSObject> receiver, | 1405 Handle<JSObject> receiver, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1522 return generic_stub(); | 1459 return generic_stub(); |
1523 } | 1460 } |
1524 return Handle<Code>::null(); | 1461 return Handle<Code>::null(); |
1525 } | 1462 } |
1526 | 1463 |
1527 | 1464 |
1528 static bool LookupForWrite(Handle<JSObject> receiver, | 1465 static bool LookupForWrite(Handle<JSObject> receiver, |
1529 Handle<String> name, | 1466 Handle<String> name, |
1530 Handle<Object> value, | 1467 Handle<Object> value, |
1531 LookupResult* lookup, | 1468 LookupResult* lookup, |
1532 IC::State* state) { | 1469 IC* ic) { |
1533 Handle<JSObject> holder = receiver; | 1470 Handle<JSObject> holder = receiver; |
1534 receiver->Lookup(*name, lookup); | 1471 receiver->Lookup(*name, lookup); |
1535 if (lookup->IsFound()) { | 1472 if (lookup->IsFound()) { |
1536 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; | 1473 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; |
1537 | 1474 |
1538 if (lookup->holder() == *receiver) { | 1475 if (lookup->holder() == *receiver) { |
1539 if (lookup->IsInterceptor() && | 1476 if (lookup->IsInterceptor() && |
1540 receiver->GetNamedInterceptor()->setter()->IsUndefined()) { | 1477 receiver->GetNamedInterceptor()->setter()->IsUndefined()) { |
1541 receiver->LocalLookupRealNamedProperty(*name, lookup); | 1478 receiver->LocalLookupRealNamedProperty(*name, lookup); |
1542 return lookup->IsFound() && | 1479 return lookup->IsFound() && |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1576 ASSERT(!receiver->map()->is_deprecated()); | 1513 ASSERT(!receiver->map()->is_deprecated()); |
1577 if (!value->FitsRepresentation(target_details.representation())) { | 1514 if (!value->FitsRepresentation(target_details.representation())) { |
1578 Handle<Map> target(lookup->GetTransitionMapFromMap(receiver->map())); | 1515 Handle<Map> target(lookup->GetTransitionMapFromMap(receiver->map())); |
1579 Map::GeneralizeRepresentation( | 1516 Map::GeneralizeRepresentation( |
1580 target, target->LastAdded(), | 1517 target, target->LastAdded(), |
1581 value->OptimalRepresentation(), FORCE_FIELD); | 1518 value->OptimalRepresentation(), FORCE_FIELD); |
1582 // Lookup the transition again since the transition tree may have changed | 1519 // Lookup the transition again since the transition tree may have changed |
1583 // entirely by the migration above. | 1520 // entirely by the migration above. |
1584 receiver->map()->LookupTransition(*holder, *name, lookup); | 1521 receiver->map()->LookupTransition(*holder, *name, lookup); |
1585 if (!lookup->IsTransition()) return false; | 1522 if (!lookup->IsTransition()) return false; |
1586 *state = MONOMORPHIC_PROTOTYPE_FAILURE; | 1523 ic->MarkMonomorphicPrototypeFailure(); |
1587 } | 1524 } |
1588 return true; | 1525 return true; |
1589 } | 1526 } |
1590 | 1527 |
1591 | 1528 |
1592 MaybeObject* StoreIC::Store(State state, | 1529 MaybeObject* StoreIC::Store(Handle<Object> object, |
1593 Handle<Object> object, | |
1594 Handle<String> name, | 1530 Handle<String> name, |
1595 Handle<Object> value, | 1531 Handle<Object> value, |
1596 JSReceiver::StoreFromKeyed store_mode) { | 1532 JSReceiver::StoreFromKeyed store_mode) { |
1597 // Handle proxies. | 1533 // Handle proxies. |
1598 if (object->IsJSProxy()) { | 1534 if (object->IsJSProxy()) { |
1599 Handle<Object> result = JSReceiver::SetProperty( | 1535 Handle<Object> result = JSReceiver::SetProperty( |
1600 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode()); | 1536 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode()); |
1601 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1537 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1602 return *result; | 1538 return *result; |
1603 } | 1539 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1649 // to have fast properties but a read-only length. | 1585 // to have fast properties but a read-only length. |
1650 if (use_ic && | 1586 if (use_ic && |
1651 receiver->IsJSArray() && | 1587 receiver->IsJSArray() && |
1652 name->Equals(isolate()->heap()->length_string()) && | 1588 name->Equals(isolate()->heap()->length_string()) && |
1653 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1589 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
1654 receiver->HasFastProperties() && | 1590 receiver->HasFastProperties() && |
1655 !receiver->map()->is_frozen()) { | 1591 !receiver->map()->is_frozen()) { |
1656 Handle<Code> stub = | 1592 Handle<Code> stub = |
1657 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); | 1593 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); |
1658 set_target(*stub); | 1594 set_target(*stub); |
1659 TRACE_IC("StoreIC", name, state, stub); | 1595 TRACE_IC("StoreIC", name, stub); |
1660 Handle<Object> result = JSReceiver::SetProperty( | 1596 Handle<Object> result = JSReceiver::SetProperty( |
1661 receiver, name, value, NONE, strict_mode(), store_mode); | 1597 receiver, name, value, NONE, strict_mode(), store_mode); |
1662 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1598 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1663 return *result; | 1599 return *result; |
1664 } | 1600 } |
1665 | 1601 |
1666 if (receiver->IsJSGlobalProxy()) { | 1602 if (receiver->IsJSGlobalProxy()) { |
1667 if (use_ic && kind() != Code::KEYED_STORE_IC) { | 1603 if (use_ic && kind() != Code::KEYED_STORE_IC) { |
1668 // Generate a generic stub that goes to the runtime when we see a global | 1604 // Generate a generic stub that goes to the runtime when we see a global |
1669 // proxy as receiver. | 1605 // proxy as receiver. |
1670 Handle<Code> stub = global_proxy_stub(); | 1606 Handle<Code> stub = global_proxy_stub(); |
1671 set_target(*stub); | 1607 set_target(*stub); |
1672 TRACE_IC("StoreIC", name, state, stub); | 1608 TRACE_IC("StoreIC", name, stub); |
1673 } | 1609 } |
1674 Handle<Object> result = JSReceiver::SetProperty( | 1610 Handle<Object> result = JSReceiver::SetProperty( |
1675 receiver, name, value, NONE, strict_mode(), store_mode); | 1611 receiver, name, value, NONE, strict_mode(), store_mode); |
1676 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1612 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1677 return *result; | 1613 return *result; |
1678 } | 1614 } |
1679 | 1615 |
1680 LookupResult lookup(isolate()); | 1616 LookupResult lookup(isolate()); |
1681 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); | 1617 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); |
1682 if (!can_store && | 1618 if (!can_store && |
1683 strict_mode() == kStrictMode && | 1619 strict_mode() == kStrictMode && |
1684 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1620 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
1685 IsUndeclaredGlobal(object)) { | 1621 IsUndeclaredGlobal(object)) { |
1686 // Strict mode doesn't allow setting non-existent global property. | 1622 // Strict mode doesn't allow setting non-existent global property. |
1687 return ReferenceError("not_defined", name); | 1623 return ReferenceError("not_defined", name); |
1688 } | 1624 } |
1689 if (use_ic) { | 1625 if (use_ic) { |
1690 if (state == UNINITIALIZED) { | 1626 if (state() == UNINITIALIZED) { |
1691 Handle<Code> stub = pre_monomorphic_stub(); | 1627 Handle<Code> stub = pre_monomorphic_stub(); |
1692 set_target(*stub); | 1628 set_target(*stub); |
1693 TRACE_IC("StoreIC", name, state, stub); | 1629 TRACE_IC("StoreIC", name, stub); |
1694 } else if (can_store) { | 1630 } else if (can_store) { |
1695 UpdateCaches(&lookup, state, receiver, name, value); | 1631 UpdateCaches(&lookup, receiver, name, value); |
1696 } else if (!name->IsCacheable(isolate()) || | 1632 } else if (!name->IsCacheable(isolate()) || |
1697 lookup.IsNormal() || | 1633 lookup.IsNormal() || |
1698 (lookup.IsField() && lookup.CanHoldValue(value))) { | 1634 (lookup.IsField() && lookup.CanHoldValue(value))) { |
1699 Handle<Code> stub = generic_stub(); | 1635 Handle<Code> stub = generic_stub(); |
1700 set_target(*stub); | 1636 set_target(*stub); |
1701 } | 1637 } |
1702 } | 1638 } |
1703 | 1639 |
1704 // Set the property. | 1640 // Set the property. |
1705 Handle<Object> result = JSReceiver::SetProperty( | 1641 Handle<Object> result = JSReceiver::SetProperty( |
1706 receiver, name, value, NONE, strict_mode(), store_mode); | 1642 receiver, name, value, NONE, strict_mode(), store_mode); |
1707 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1643 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1708 return *result; | 1644 return *result; |
1709 } | 1645 } |
1710 | 1646 |
1711 | 1647 |
1712 void StoreIC::UpdateCaches(LookupResult* lookup, | 1648 void StoreIC::UpdateCaches(LookupResult* lookup, |
1713 State state, | |
1714 Handle<JSObject> receiver, | 1649 Handle<JSObject> receiver, |
1715 Handle<String> name, | 1650 Handle<String> name, |
1716 Handle<Object> value) { | 1651 Handle<Object> value) { |
1717 ASSERT(!receiver->IsJSGlobalProxy()); | 1652 ASSERT(!receiver->IsJSGlobalProxy()); |
1718 ASSERT(lookup->IsFound()); | 1653 ASSERT(lookup->IsFound()); |
1719 | 1654 |
1720 // These are not cacheable, so we never see such LookupResults here. | 1655 // These are not cacheable, so we never see such LookupResults here. |
1721 ASSERT(!lookup->IsHandler()); | 1656 ASSERT(!lookup->IsHandler()); |
1722 | 1657 |
1723 Handle<Code> code = ComputeStoreMonomorphic(lookup, receiver, name, value); | 1658 Handle<Code> code = ComputeStoreMonomorphic(lookup, receiver, name, value); |
1724 if (code.is_null()) { | 1659 if (code.is_null()) { |
1725 set_target(*generic_stub()); | 1660 set_target(*generic_stub()); |
1726 return; | 1661 return; |
1727 } | 1662 } |
1728 | 1663 |
1729 PatchCache(state, receiver, name, code); | 1664 PatchCache(receiver, name, code); |
1730 TRACE_IC("StoreIC", name, state, target()); | 1665 TRACE_IC("StoreIC", name, target()); |
1731 } | 1666 } |
1732 | 1667 |
1733 | 1668 |
1734 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, | 1669 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
1735 Handle<JSObject> receiver, | 1670 Handle<JSObject> receiver, |
1736 Handle<String> name, | 1671 Handle<String> name, |
1737 Handle<Object> value) { | 1672 Handle<Object> value) { |
1738 Handle<JSObject> holder(lookup->holder()); | 1673 Handle<JSObject> holder(lookup->holder()); |
1739 switch (lookup->type()) { | 1674 switch (lookup->type()) { |
1740 case FIELD: | 1675 case FIELD: |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1819 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, | 1754 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
1820 KeyedAccessStoreMode store_mode) { | 1755 KeyedAccessStoreMode store_mode) { |
1821 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1756 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
1822 // via megamorphic stubs, since they don't have a map in their relocation info | 1757 // via megamorphic stubs, since they don't have a map in their relocation info |
1823 // and so the stubs can't be harvested for the object needed for a map check. | 1758 // and so the stubs can't be harvested for the object needed for a map check. |
1824 if (target()->type() != Code::NORMAL) { | 1759 if (target()->type() != Code::NORMAL) { |
1825 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); | 1760 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); |
1826 return generic_stub(); | 1761 return generic_stub(); |
1827 } | 1762 } |
1828 | 1763 |
1829 State ic_state = target()->ic_state(); | |
1830 Handle<Map> receiver_map(receiver->map(), isolate()); | 1764 Handle<Map> receiver_map(receiver->map(), isolate()); |
1831 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { | 1765 if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) { |
1832 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1766 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state |
1833 // yet will do so and stay there. | 1767 // yet will do so and stay there. |
1834 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); | 1768 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); |
1835 store_mode = GetNonTransitioningStoreMode(store_mode); | 1769 store_mode = GetNonTransitioningStoreMode(store_mode); |
1836 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1770 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
1837 monomorphic_map, strict_mode(), store_mode); | 1771 monomorphic_map, strict_mode(), store_mode); |
1838 } | 1772 } |
1839 | 1773 |
1840 MapHandleList target_receiver_maps; | 1774 MapHandleList target_receiver_maps; |
1841 target()->FindAllMaps(&target_receiver_maps); | 1775 target()->FindAllMaps(&target_receiver_maps); |
1842 if (target_receiver_maps.length() == 0) { | 1776 if (target_receiver_maps.length() == 0) { |
1843 // In the case that there is a non-map-specific IC is installed (e.g. keyed | 1777 // In the case that there is a non-map-specific IC is installed (e.g. keyed |
1844 // stores into properties in dictionary mode), then there will be not | 1778 // stores into properties in dictionary mode), then there will be not |
1845 // receiver maps in the target. | 1779 // receiver maps in the target. |
1846 return generic_stub(); | 1780 return generic_stub(); |
1847 } | 1781 } |
1848 | 1782 |
1849 // There are several special cases where an IC that is MONOMORPHIC can still | 1783 // There are several special cases where an IC that is MONOMORPHIC can still |
1850 // transition to a different GetNonTransitioningStoreMode IC that handles a | 1784 // transition to a different GetNonTransitioningStoreMode IC that handles a |
1851 // superset of the original IC. Handle those here if the receiver map hasn't | 1785 // superset of the original IC. Handle those here if the receiver map hasn't |
1852 // changed or it has transitioned to a more general kind. | 1786 // changed or it has transitioned to a more general kind. |
1853 KeyedAccessStoreMode old_store_mode = | 1787 KeyedAccessStoreMode old_store_mode = |
1854 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); | 1788 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); |
1855 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | 1789 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); |
1856 if (ic_state == MONOMORPHIC) { | 1790 if (state() == MONOMORPHIC) { |
1857 // If the "old" and "new" maps are in the same elements map family, stay | 1791 // If the "old" and "new" maps are in the same elements map family, stay |
1858 // MONOMORPHIC and use the map for the most generic ElementsKind. | 1792 // MONOMORPHIC and use the map for the most generic ElementsKind. |
1859 Handle<Map> transitioned_receiver_map = receiver_map; | 1793 Handle<Map> transitioned_receiver_map = receiver_map; |
1860 if (IsTransitionStoreMode(store_mode)) { | 1794 if (IsTransitionStoreMode(store_mode)) { |
1861 transitioned_receiver_map = | 1795 transitioned_receiver_map = |
1862 ComputeTransitionedMap(receiver, store_mode); | 1796 ComputeTransitionedMap(receiver, store_mode); |
1863 } | 1797 } |
1864 if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { | 1798 if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { |
1865 // Element family is the same, use the "worst" case map. | 1799 // Element family is the same, use the "worst" case map. |
1866 store_mode = GetNonTransitioningStoreMode(store_mode); | 1800 store_mode = GetNonTransitioningStoreMode(store_mode); |
1867 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1801 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
1868 transitioned_receiver_map, strict_mode(), store_mode); | 1802 transitioned_receiver_map, strict_mode(), store_mode); |
1869 } else if (*previous_receiver_map == receiver->map() && | 1803 } else if (*previous_receiver_map == receiver->map() && |
1870 old_store_mode == STANDARD_STORE && | 1804 old_store_mode == STANDARD_STORE && |
1871 (IsGrowStoreMode(store_mode) || | 1805 (IsGrowStoreMode(store_mode) || |
1872 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1806 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
1873 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { | 1807 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { |
1874 // A "normal" IC that handles stores can switch to a version that can | 1808 // A "normal" IC that handles stores can switch to a version that can |
1875 // grow at the end of the array, handle OOB accesses or copy COW arrays | 1809 // grow at the end of the array, handle OOB accesses or copy COW arrays |
1876 // and still stay MONOMORPHIC. | 1810 // and still stay MONOMORPHIC. |
1877 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1811 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
1878 receiver_map, strict_mode(), store_mode); | 1812 receiver_map, strict_mode(), store_mode); |
1879 } | 1813 } |
1880 } | 1814 } |
1881 | 1815 |
1882 ASSERT(ic_state != GENERIC); | 1816 ASSERT(state() != GENERIC); |
1883 | 1817 |
1884 bool map_added = | 1818 bool map_added = |
1885 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); | 1819 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); |
1886 | 1820 |
1887 if (IsTransitionStoreMode(store_mode)) { | 1821 if (IsTransitionStoreMode(store_mode)) { |
1888 Handle<Map> transitioned_receiver_map = | 1822 Handle<Map> transitioned_receiver_map = |
1889 ComputeTransitionedMap(receiver, store_mode); | 1823 ComputeTransitionedMap(receiver, store_mode); |
1890 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, | 1824 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, |
1891 transitioned_receiver_map); | 1825 transitioned_receiver_map); |
1892 } | 1826 } |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2052 Heap* heap = receiver->GetHeap(); | 1986 Heap* heap = receiver->GetHeap(); |
2053 if (receiver->elements()->map() == heap->fixed_cow_array_map()) { | 1987 if (receiver->elements()->map() == heap->fixed_cow_array_map()) { |
2054 return STORE_NO_TRANSITION_HANDLE_COW; | 1988 return STORE_NO_TRANSITION_HANDLE_COW; |
2055 } else { | 1989 } else { |
2056 return STANDARD_STORE; | 1990 return STANDARD_STORE; |
2057 } | 1991 } |
2058 } | 1992 } |
2059 } | 1993 } |
2060 | 1994 |
2061 | 1995 |
2062 MaybeObject* KeyedStoreIC::Store(State state, | 1996 MaybeObject* KeyedStoreIC::Store(Handle<Object> object, |
2063 Handle<Object> object, | |
2064 Handle<Object> key, | 1997 Handle<Object> key, |
2065 Handle<Object> value, | 1998 Handle<Object> value, |
2066 ICMissMode miss_mode) { | 1999 ICMissMode miss_mode) { |
2067 // Check for values that can be converted into an internalized string directly | 2000 // Check for values that can be converted into an internalized string directly |
2068 // or is representable as a smi. | 2001 // or is representable as a smi. |
2069 key = TryConvertKey(key, isolate()); | 2002 key = TryConvertKey(key, isolate()); |
2070 | 2003 |
2071 if (key->IsInternalizedString()) { | 2004 if (key->IsInternalizedString()) { |
2072 return StoreIC::Store(state, | 2005 return StoreIC::Store(object, |
2073 object, | |
2074 Handle<String>::cast(key), | 2006 Handle<String>::cast(key), |
2075 value, | 2007 value, |
2076 JSReceiver::MAY_BE_STORE_FROM_KEYED); | 2008 JSReceiver::MAY_BE_STORE_FROM_KEYED); |
2077 } | 2009 } |
2078 | 2010 |
2079 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && | 2011 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && |
2080 !(FLAG_harmony_observation && object->IsJSObject() && | 2012 !(FLAG_harmony_observation && object->IsJSObject() && |
2081 JSObject::cast(*object)->map()->is_observed()); | 2013 JSObject::cast(*object)->map()->is_observed()); |
2082 if (use_ic && !object->IsSmi()) { | 2014 if (use_ic && !object->IsSmi()) { |
2083 // Don't use ICs for maps of the objects in Array's prototype chain. We | 2015 // Don't use ICs for maps of the objects in Array's prototype chain. We |
(...skipping 24 matching lines...) Expand all Loading... |
2108 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); | 2040 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); |
2109 } | 2041 } |
2110 } else { | 2042 } else { |
2111 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object"); | 2043 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object"); |
2112 } | 2044 } |
2113 } else { | 2045 } else { |
2114 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); | 2046 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); |
2115 } | 2047 } |
2116 ASSERT(!stub.is_null()); | 2048 ASSERT(!stub.is_null()); |
2117 set_target(*stub); | 2049 set_target(*stub); |
2118 TRACE_IC("KeyedStoreIC", key, state, target()); | 2050 TRACE_IC("KeyedStoreIC", key, target()); |
2119 } | 2051 } |
2120 | 2052 |
2121 return Runtime::SetObjectPropertyOrFail( | 2053 return Runtime::SetObjectPropertyOrFail( |
2122 isolate(), object , key, value, NONE, strict_mode()); | 2054 isolate(), object , key, value, NONE, strict_mode()); |
2123 } | 2055 } |
2124 | 2056 |
2125 | 2057 |
2126 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, | 2058 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
2127 Handle<JSObject> receiver, | 2059 Handle<JSObject> receiver, |
2128 Handle<String> name, | 2060 Handle<String> name, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2171 | 2103 |
2172 // ---------------------------------------------------------------------------- | 2104 // ---------------------------------------------------------------------------- |
2173 // Static IC stub generators. | 2105 // Static IC stub generators. |
2174 // | 2106 // |
2175 | 2107 |
2176 // Used from ic-<arch>.cc. | 2108 // Used from ic-<arch>.cc. |
2177 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | 2109 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { |
2178 HandleScope scope(isolate); | 2110 HandleScope scope(isolate); |
2179 ASSERT(args.length() == 2); | 2111 ASSERT(args.length() == 2); |
2180 CallIC ic(isolate); | 2112 CallIC ic(isolate); |
2181 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2113 ic.UpdateState(args[0], args[1]); |
2182 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2114 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
2183 MaybeObject* maybe_result = ic.LoadFunction(state, | 2115 MaybeObject* maybe_result = ic.LoadFunction(extra_ic_state, |
2184 extra_ic_state, | |
2185 args.at<Object>(0), | 2116 args.at<Object>(0), |
2186 args.at<String>(1)); | 2117 args.at<String>(1)); |
2187 JSFunction* raw_function; | 2118 JSFunction* raw_function; |
2188 if (!maybe_result->To(&raw_function)) return maybe_result; | 2119 if (!maybe_result->To(&raw_function)) return maybe_result; |
2189 | 2120 |
2190 // The first time the inline cache is updated may be the first time the | 2121 // The first time the inline cache is updated may be the first time the |
2191 // function it references gets called. If the function is lazily compiled | 2122 // function it references gets called. If the function is lazily compiled |
2192 // then the first call will trigger a compilation. We check for this case | 2123 // then the first call will trigger a compilation. We check for this case |
2193 // and we do the compilation immediately, instead of waiting for the stub | 2124 // and we do the compilation immediately, instead of waiting for the stub |
2194 // currently attached to the JSFunction object to trigger compilation. | 2125 // currently attached to the JSFunction object to trigger compilation. |
2195 if (raw_function->is_compiled()) return raw_function; | 2126 if (raw_function->is_compiled()) return raw_function; |
2196 | 2127 |
2197 Handle<JSFunction> function(raw_function); | 2128 Handle<JSFunction> function(raw_function); |
2198 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); | 2129 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); |
2199 return *function; | 2130 return *function; |
2200 } | 2131 } |
2201 | 2132 |
2202 | 2133 |
2203 // Used from ic-<arch>.cc. | 2134 // Used from ic-<arch>.cc. |
2204 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { | 2135 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { |
2205 HandleScope scope(isolate); | 2136 HandleScope scope(isolate); |
2206 ASSERT(args.length() == 2); | 2137 ASSERT(args.length() == 2); |
2207 KeyedCallIC ic(isolate); | 2138 KeyedCallIC ic(isolate); |
2208 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2139 ic.UpdateState(args[0], args[1]); |
2209 MaybeObject* maybe_result = | 2140 MaybeObject* maybe_result = |
2210 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); | 2141 ic.LoadFunction(args.at<Object>(0), args.at<Object>(1)); |
2211 // Result could be a function or a failure. | 2142 // Result could be a function or a failure. |
2212 JSFunction* raw_function = NULL; | 2143 JSFunction* raw_function = NULL; |
2213 if (!maybe_result->To(&raw_function)) return maybe_result; | 2144 if (!maybe_result->To(&raw_function)) return maybe_result; |
2214 | 2145 |
2215 if (raw_function->is_compiled()) return raw_function; | 2146 if (raw_function->is_compiled()) return raw_function; |
2216 | 2147 |
2217 Handle<JSFunction> function(raw_function, isolate); | 2148 Handle<JSFunction> function(raw_function, isolate); |
2218 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); | 2149 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); |
2219 return *function; | 2150 return *function; |
2220 } | 2151 } |
2221 | 2152 |
2222 | 2153 |
2223 // Used from ic-<arch>.cc. | 2154 // Used from ic-<arch>.cc. |
2224 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 2155 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
2225 HandleScope scope(isolate); | 2156 HandleScope scope(isolate); |
2226 ASSERT(args.length() == 2); | 2157 ASSERT(args.length() == 2); |
2227 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2158 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
2228 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2159 ic.UpdateState(args[0], args[1]); |
2229 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 2160 return ic.Load(args.at<Object>(0), args.at<String>(1)); |
2230 } | 2161 } |
2231 | 2162 |
2232 | 2163 |
2233 // Used from ic-<arch>.cc | 2164 // Used from ic-<arch>.cc |
2234 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { | 2165 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { |
2235 HandleScope scope(isolate); | 2166 HandleScope scope(isolate); |
2236 ASSERT(args.length() == 2); | 2167 ASSERT(args.length() == 2); |
2237 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2168 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
2238 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2169 ic.UpdateState(args[0], args[1]); |
2239 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), MISS); | 2170 return ic.Load(args.at<Object>(0), args.at<Object>(1), MISS); |
2240 } | 2171 } |
2241 | 2172 |
2242 | 2173 |
2243 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { | 2174 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { |
2244 HandleScope scope(isolate); | 2175 HandleScope scope(isolate); |
2245 ASSERT(args.length() == 2); | 2176 ASSERT(args.length() == 2); |
2246 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2177 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2247 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2178 ic.UpdateState(args[0], args[1]); |
2248 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), MISS); | 2179 return ic.Load(args.at<Object>(0), args.at<Object>(1), MISS); |
2249 } | 2180 } |
2250 | 2181 |
2251 | 2182 |
2252 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { | 2183 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { |
2253 HandleScope scope(isolate); | 2184 HandleScope scope(isolate); |
2254 ASSERT(args.length() == 2); | 2185 ASSERT(args.length() == 2); |
2255 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2186 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
2256 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2187 ic.UpdateState(args[0], args[1]); |
2257 return ic.Load(state, | 2188 return ic.Load(args.at<Object>(0), |
2258 args.at<Object>(0), | |
2259 args.at<Object>(1), | 2189 args.at<Object>(1), |
2260 MISS_FORCE_GENERIC); | 2190 MISS_FORCE_GENERIC); |
2261 } | 2191 } |
2262 | 2192 |
2263 | 2193 |
2264 // Used from ic-<arch>.cc. | 2194 // Used from ic-<arch>.cc. |
2265 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { | 2195 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { |
2266 HandleScope scope(isolate); | 2196 HandleScope scope(isolate); |
2267 ASSERT(args.length() == 3); | 2197 ASSERT(args.length() == 3); |
2268 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2198 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2269 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2199 ic.UpdateState(args[0], args[1]); |
2270 return ic.Store(state, | 2200 return ic.Store(args.at<Object>(0), |
2271 args.at<Object>(0), | |
2272 args.at<String>(1), | 2201 args.at<String>(1), |
2273 args.at<Object>(2)); | 2202 args.at<Object>(2)); |
2274 } | 2203 } |
2275 | 2204 |
2276 | 2205 |
2277 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { | 2206 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { |
2278 HandleScope scope(isolate); | 2207 HandleScope scope(isolate); |
2279 ASSERT(args.length() == 3); | 2208 ASSERT(args.length() == 3); |
2280 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2209 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2281 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2210 ic.UpdateState(args[0], args[1]); |
2282 return ic.Store(state, | 2211 return ic.Store(args.at<Object>(0), |
2283 args.at<Object>(0), | |
2284 args.at<String>(1), | 2212 args.at<String>(1), |
2285 args.at<Object>(2)); | 2213 args.at<Object>(2)); |
2286 } | 2214 } |
2287 | 2215 |
2288 | 2216 |
2289 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { | 2217 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { |
2290 SealHandleScope shs(isolate); | 2218 SealHandleScope shs(isolate); |
2291 | 2219 |
2292 ASSERT(args.length() == 2); | 2220 ASSERT(args.length() == 2); |
2293 JSArray* receiver = JSArray::cast(args[0]); | 2221 JSArray* receiver = JSArray::cast(args[0]); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2358 // Return the stored value. | 2286 // Return the stored value. |
2359 return value; | 2287 return value; |
2360 } | 2288 } |
2361 | 2289 |
2362 | 2290 |
2363 // Used from ic-<arch>.cc. | 2291 // Used from ic-<arch>.cc. |
2364 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { | 2292 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { |
2365 HandleScope scope(isolate); | 2293 HandleScope scope(isolate); |
2366 ASSERT(args.length() == 3); | 2294 ASSERT(args.length() == 3); |
2367 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2295 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2368 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2296 ic.UpdateState(args[0], args[1]); |
2369 return ic.Store(state, | 2297 return ic.Store(args.at<Object>(0), |
2370 args.at<Object>(0), | |
2371 args.at<Object>(1), | 2298 args.at<Object>(1), |
2372 args.at<Object>(2), | 2299 args.at<Object>(2), |
2373 MISS); | 2300 MISS); |
2374 } | 2301 } |
2375 | 2302 |
2376 | 2303 |
2377 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { | 2304 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { |
2378 HandleScope scope(isolate); | 2305 HandleScope scope(isolate); |
2379 ASSERT(args.length() == 3); | 2306 ASSERT(args.length() == 3); |
2380 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2307 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2381 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2308 ic.UpdateState(args[0], args[1]); |
2382 return ic.Store(state, | 2309 return ic.Store(args.at<Object>(0), |
2383 args.at<Object>(0), | |
2384 args.at<Object>(1), | 2310 args.at<Object>(1), |
2385 args.at<Object>(2), | 2311 args.at<Object>(2), |
2386 MISS); | 2312 MISS); |
2387 } | 2313 } |
2388 | 2314 |
2389 | 2315 |
2390 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { | 2316 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { |
2391 HandleScope scope(isolate); | 2317 HandleScope scope(isolate); |
2392 ASSERT(args.length() == 3); | 2318 ASSERT(args.length() == 3); |
2393 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2319 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
(...skipping 26 matching lines...) Expand all Loading... |
2420 value, | 2346 value, |
2421 NONE, | 2347 NONE, |
2422 strict_mode); | 2348 strict_mode); |
2423 } | 2349 } |
2424 | 2350 |
2425 | 2351 |
2426 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { | 2352 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { |
2427 HandleScope scope(isolate); | 2353 HandleScope scope(isolate); |
2428 ASSERT(args.length() == 3); | 2354 ASSERT(args.length() == 3); |
2429 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2355 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2430 IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); | 2356 ic.UpdateState(args[0], args[1]); |
2431 return ic.Store(state, | 2357 return ic.Store(args.at<Object>(0), |
2432 args.at<Object>(0), | |
2433 args.at<Object>(1), | 2358 args.at<Object>(1), |
2434 args.at<Object>(2), | 2359 args.at<Object>(2), |
2435 MISS_FORCE_GENERIC); | 2360 MISS_FORCE_GENERIC); |
2436 } | 2361 } |
2437 | 2362 |
2438 | 2363 |
2439 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { | 2364 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { |
2440 HandleScope scope(isolate); | 2365 HandleScope scope(isolate); |
2441 ASSERT(args.length() == 4); | 2366 ASSERT(args.length() == 4); |
2442 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2367 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2951 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { | 2876 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { |
2952 HandleScope scope(isolate); | 2877 HandleScope scope(isolate); |
2953 ASSERT(args.length() == 3); | 2878 ASSERT(args.length() == 3); |
2954 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); | 2879 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); |
2955 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2880 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
2956 return ic.raw_target(); | 2881 return ic.raw_target(); |
2957 } | 2882 } |
2958 | 2883 |
2959 | 2884 |
2960 void CompareNilIC::Clear(Address address, Code* target) { | 2885 void CompareNilIC::Clear(Address address, Code* target) { |
2961 if (target->ic_state() == UNINITIALIZED) return; | 2886 if (IsCleared(target)) return; |
2962 Code::ExtraICState state = target->extended_extra_ic_state(); | 2887 Code::ExtraICState state = target->extended_extra_ic_state(); |
2963 | 2888 |
2964 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); | 2889 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); |
2965 stub.ClearState(); | 2890 stub.ClearState(); |
2966 | 2891 |
2967 Code* code = NULL; | 2892 Code* code = NULL; |
2968 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); | 2893 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); |
2969 | 2894 |
2970 SetTargetAtAddress(address, code); | 2895 SetTargetAtAddress(address, code); |
2971 } | 2896 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3031 set_target(*code); | 2956 set_target(*code); |
3032 return Smi::FromInt(to_boolean_value ? 1 : 0); | 2957 return Smi::FromInt(to_boolean_value ? 1 : 0); |
3033 } | 2958 } |
3034 | 2959 |
3035 | 2960 |
3036 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) { | 2961 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) { |
3037 ASSERT(args.length() == 1); | 2962 ASSERT(args.length() == 1); |
3038 HandleScope scope(isolate); | 2963 HandleScope scope(isolate); |
3039 Handle<Object> object = args.at<Object>(0); | 2964 Handle<Object> object = args.at<Object>(0); |
3040 ToBooleanIC ic(isolate); | 2965 ToBooleanIC ic(isolate); |
3041 Code::ExtraICState ic_state = ic.target()->extended_extra_ic_state(); | 2966 Code::ExtraICState extra_ic_state = ic.target()->extended_extra_ic_state(); |
3042 return ic.ToBoolean(object, ic_state); | 2967 return ic.ToBoolean(object, extra_ic_state); |
3043 } | 2968 } |
3044 | 2969 |
3045 | 2970 |
3046 static const Address IC_utilities[] = { | 2971 static const Address IC_utilities[] = { |
3047 #define ADDR(name) FUNCTION_ADDR(name), | 2972 #define ADDR(name) FUNCTION_ADDR(name), |
3048 IC_UTIL_LIST(ADDR) | 2973 IC_UTIL_LIST(ADDR) |
3049 NULL | 2974 NULL |
3050 #undef ADDR | 2975 #undef ADDR |
3051 }; | 2976 }; |
3052 | 2977 |
3053 | 2978 |
3054 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2979 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3055 return IC_utilities[id]; | 2980 return IC_utilities[id]; |
3056 } | 2981 } |
3057 | 2982 |
3058 | 2983 |
3059 } } // namespace v8::internal | 2984 } } // namespace v8::internal |
OLD | NEW |