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