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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 ASSERT((TraceIC(type, name), true)) | 120 ASSERT((TraceIC(type, name), true)) |
121 | 121 |
122 IC::IC(FrameDepth depth, Isolate* isolate) | 122 IC::IC(FrameDepth depth, Isolate* isolate) |
123 : isolate_(isolate), | 123 : isolate_(isolate), |
124 target_set_(false) { | 124 target_set_(false) { |
125 // To improve the performance of the (much used) IC code, we unfold a few | 125 // To improve the performance of the (much used) IC code, we unfold a few |
126 // levels of the stack frame iteration code. This yields a ~35% speedup when | 126 // levels of the stack frame iteration code. This yields a ~35% speedup when |
127 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 127 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
128 const Address entry = | 128 const Address entry = |
129 Isolate::c_entry_fp(isolate->thread_local_top()); | 129 Isolate::c_entry_fp(isolate->thread_local_top()); |
130 Address constant_pool = NULL; | |
131 if (FLAG_enable_ool_constant_pool) { | |
132 constant_pool = Memory::Address_at( | |
133 entry + ExitFrameConstants::kConstantPoolOffset); | |
134 } | |
135 Address* pc_address = | 130 Address* pc_address = |
136 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); | 131 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); |
137 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 132 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
138 // If there's another JavaScript frame on the stack or a | 133 // If there's another JavaScript frame on the stack or a |
139 // StubFailureTrampoline, we need to look one frame further down the stack to | 134 // StubFailureTrampoline, we need to look one frame further down the stack to |
140 // find the frame pointer and the return address stack slot. | 135 // find the frame pointer and the return address stack slot. |
141 if (depth == EXTRA_CALL_FRAME) { | 136 if (depth == EXTRA_CALL_FRAME) { |
142 if (FLAG_enable_ool_constant_pool) { | |
143 constant_pool = Memory::Address_at( | |
144 fp + StandardFrameConstants::kConstantPoolOffset); | |
145 } | |
146 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; | 137 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; |
147 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); | 138 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); |
148 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); | 139 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); |
149 } | 140 } |
150 #ifdef DEBUG | 141 #ifdef DEBUG |
151 StackFrameIterator it(isolate); | 142 StackFrameIterator it(isolate); |
152 for (int i = 0; i < depth + 1; i++) it.Advance(); | 143 for (int i = 0; i < depth + 1; i++) it.Advance(); |
153 StackFrame* frame = it.frame(); | 144 StackFrame* frame = it.frame(); |
154 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); | 145 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); |
155 #endif | 146 #endif |
156 fp_ = fp; | 147 fp_ = fp; |
157 if (FLAG_enable_ool_constant_pool) { | |
158 raw_constant_pool_ = handle( | |
159 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), | |
160 isolate); | |
161 } | |
162 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 148 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); |
163 target_ = handle(raw_target(), isolate); | 149 target_ = handle(raw_target(), isolate); |
164 state_ = target_->ic_state(); | 150 state_ = target_->ic_state(); |
165 extra_ic_state_ = target_->extra_ic_state(); | 151 extra_ic_state_ = target_->extra_ic_state(); |
166 } | 152 } |
167 | 153 |
168 | 154 |
169 #ifdef ENABLE_DEBUGGER_SUPPORT | 155 #ifdef ENABLE_DEBUGGER_SUPPORT |
170 SharedFunctionInfo* IC::GetSharedFunctionInfo() const { | 156 Address IC::OriginalCodeAddress() const { |
| 157 HandleScope scope(isolate()); |
171 // Compute the JavaScript frame for the frame pointer of this IC | 158 // Compute the JavaScript frame for the frame pointer of this IC |
172 // structure. We need this to be able to find the function | 159 // structure. We need this to be able to find the function |
173 // corresponding to the frame. | 160 // corresponding to the frame. |
174 StackFrameIterator it(isolate()); | 161 StackFrameIterator it(isolate()); |
175 while (it.frame()->fp() != this->fp()) it.Advance(); | 162 while (it.frame()->fp() != this->fp()) it.Advance(); |
176 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); | 163 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); |
177 // Find the function on the stack and both the active code for the | 164 // Find the function on the stack and both the active code for the |
178 // function and the original code. | 165 // function and the original code. |
179 JSFunction* function = frame->function(); | 166 JSFunction* function = frame->function(); |
180 return function->shared(); | 167 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); |
181 } | |
182 | |
183 | |
184 Code* IC::GetCode() const { | |
185 HandleScope scope(isolate()); | |
186 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate()); | |
187 Code* code = shared->code(); | 168 Code* code = shared->code(); |
188 return code; | |
189 } | |
190 | |
191 | |
192 Code* IC::GetOriginalCode() const { | |
193 HandleScope scope(isolate()); | |
194 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate()); | |
195 ASSERT(Debug::HasDebugInfo(shared)); | 169 ASSERT(Debug::HasDebugInfo(shared)); |
196 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); | 170 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); |
197 ASSERT(original_code->IsCode()); | 171 ASSERT(original_code->IsCode()); |
198 return original_code; | 172 // Get the address of the call site in the active code. This is the |
| 173 // place where the call to DebugBreakXXX is and where the IC |
| 174 // normally would be. |
| 175 Address addr = Assembler::target_address_from_return_address(pc()); |
| 176 // Return the address in the original code. This is the place where |
| 177 // the call which has been overwritten by the DebugBreakXXX resides |
| 178 // and the place where the inline cache system should look. |
| 179 intptr_t delta = |
| 180 original_code->instruction_start() - code->instruction_start(); |
| 181 return addr + delta; |
199 } | 182 } |
200 #endif | 183 #endif |
201 | 184 |
202 | 185 |
203 static bool HasInterceptorGetter(JSObject* object) { | 186 static bool HasInterceptorGetter(JSObject* object) { |
204 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | 187 return !object->GetNamedInterceptor()->getter()->IsUndefined(); |
205 } | 188 } |
206 | 189 |
207 | 190 |
208 static bool HasInterceptorSetter(JSObject* object) { | 191 static bool HasInterceptorSetter(JSObject* object) { |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 info->change_own_type_change_checksum(); | 402 info->change_own_type_change_checksum(); |
420 } | 403 } |
421 host->set_profiler_ticks(0); | 404 host->set_profiler_ticks(0); |
422 isolate->runtime_profiler()->NotifyICChanged(); | 405 isolate->runtime_profiler()->NotifyICChanged(); |
423 // TODO(2029): When an optimized function is patched, it would | 406 // TODO(2029): When an optimized function is patched, it would |
424 // be nice to propagate the corresponding type information to its | 407 // be nice to propagate the corresponding type information to its |
425 // unoptimized version for the benefit of later inlining. | 408 // unoptimized version for the benefit of later inlining. |
426 } | 409 } |
427 | 410 |
428 | 411 |
429 void IC::Clear(Isolate* isolate, Address address, | 412 void IC::Clear(Isolate* isolate, Address address) { |
430 ConstantPoolArray* constant_pool) { | 413 Code* target = GetTargetAtAddress(address); |
431 Code* target = GetTargetAtAddress(address, constant_pool); | |
432 | 414 |
433 // Don't clear debug break inline cache as it will remove the break point. | 415 // Don't clear debug break inline cache as it will remove the break point. |
434 if (target->is_debug_stub()) return; | 416 if (target->is_debug_stub()) return; |
435 | 417 |
436 switch (target->kind()) { | 418 switch (target->kind()) { |
437 case Code::LOAD_IC: | 419 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); |
438 return LoadIC::Clear(isolate, address, target, constant_pool); | |
439 case Code::KEYED_LOAD_IC: | 420 case Code::KEYED_LOAD_IC: |
440 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); | 421 return KeyedLoadIC::Clear(isolate, address, target); |
441 case Code::STORE_IC: | 422 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); |
442 return StoreIC::Clear(isolate, address, target, constant_pool); | |
443 case Code::KEYED_STORE_IC: | 423 case Code::KEYED_STORE_IC: |
444 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); | 424 return KeyedStoreIC::Clear(isolate, address, target); |
445 case Code::COMPARE_IC: | 425 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); |
446 return CompareIC::Clear(isolate, address, target, constant_pool); | 426 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); |
447 case Code::COMPARE_NIL_IC: | |
448 return CompareNilIC::Clear(address, target, constant_pool); | |
449 case Code::BINARY_OP_IC: | 427 case Code::BINARY_OP_IC: |
450 case Code::TO_BOOLEAN_IC: | 428 case Code::TO_BOOLEAN_IC: |
451 // Clearing these is tricky and does not | 429 // Clearing these is tricky and does not |
452 // make any performance difference. | 430 // make any performance difference. |
453 return; | 431 return; |
454 default: UNREACHABLE(); | 432 default: UNREACHABLE(); |
455 } | 433 } |
456 } | 434 } |
457 | 435 |
458 | 436 |
459 void KeyedLoadIC::Clear(Isolate* isolate, | 437 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
460 Address address, | |
461 Code* target, | |
462 ConstantPoolArray* constant_pool) { | |
463 if (IsCleared(target)) return; | 438 if (IsCleared(target)) return; |
464 // Make sure to also clear the map used in inline fast cases. If we | 439 // Make sure to also clear the map used in inline fast cases. If we |
465 // do not clear these maps, cached code can keep objects alive | 440 // do not clear these maps, cached code can keep objects alive |
466 // through the embedded maps. | 441 // through the embedded maps. |
467 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); | 442 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); |
468 } | 443 } |
469 | 444 |
470 | 445 |
471 void LoadIC::Clear(Isolate* isolate, | 446 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
472 Address address, | |
473 Code* target, | |
474 ConstantPoolArray* constant_pool) { | |
475 if (IsCleared(target)) return; | 447 if (IsCleared(target)) return; |
476 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( | 448 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( |
477 Code::LOAD_IC, target->extra_ic_state()); | 449 Code::LOAD_IC, target->extra_ic_state()); |
478 SetTargetAtAddress(address, code, constant_pool); | 450 SetTargetAtAddress(address, code); |
479 } | 451 } |
480 | 452 |
481 | 453 |
482 void StoreIC::Clear(Isolate* isolate, | 454 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { |
483 Address address, | |
484 Code* target, | |
485 ConstantPoolArray* constant_pool) { | |
486 if (IsCleared(target)) return; | 455 if (IsCleared(target)) return; |
487 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( | 456 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( |
488 Code::STORE_IC, target->extra_ic_state()); | 457 Code::STORE_IC, target->extra_ic_state()); |
489 SetTargetAtAddress(address, code, constant_pool); | 458 SetTargetAtAddress(address, code); |
490 } | 459 } |
491 | 460 |
492 | 461 |
493 void KeyedStoreIC::Clear(Isolate* isolate, | 462 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { |
494 Address address, | |
495 Code* target, | |
496 ConstantPoolArray* constant_pool) { | |
497 if (IsCleared(target)) return; | 463 if (IsCleared(target)) return; |
498 SetTargetAtAddress(address, | 464 SetTargetAtAddress(address, |
499 *pre_monomorphic_stub( | 465 *pre_monomorphic_stub( |
500 isolate, StoreIC::GetStrictMode(target->extra_ic_state())), | 466 isolate, StoreIC::GetStrictMode(target->extra_ic_state()))); |
501 constant_pool); | |
502 } | 467 } |
503 | 468 |
504 | 469 |
505 void CompareIC::Clear(Isolate* isolate, | 470 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { |
506 Address address, | |
507 Code* target, | |
508 ConstantPoolArray* constant_pool) { | |
509 ASSERT(target->major_key() == CodeStub::CompareIC); | 471 ASSERT(target->major_key() == CodeStub::CompareIC); |
510 CompareIC::State handler_state; | 472 CompareIC::State handler_state; |
511 Token::Value op; | 473 Token::Value op; |
512 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, | 474 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, |
513 &handler_state, &op); | 475 &handler_state, &op); |
514 // Only clear CompareICs that can retain objects. | 476 // Only clear CompareICs that can retain objects. |
515 if (handler_state != KNOWN_OBJECT) return; | 477 if (handler_state != KNOWN_OBJECT) return; |
516 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool); | 478 SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); |
517 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 479 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
518 } | 480 } |
519 | 481 |
520 | 482 |
521 static bool MigrateDeprecated(Handle<Object> object) { | 483 static bool MigrateDeprecated(Handle<Object> object) { |
522 if (!object->IsJSObject()) return false; | 484 if (!object->IsJSObject()) return false; |
523 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 485 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
524 if (!receiver->map()->is_deprecated()) return false; | 486 if (!receiver->map()->is_deprecated()) return false; |
525 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 487 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
526 return true; | 488 return true; |
(...skipping 2189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2716 | 2678 |
2717 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. | 2679 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. |
2718 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { | 2680 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { |
2719 HandleScope scope(isolate); | 2681 HandleScope scope(isolate); |
2720 ASSERT(args.length() == 3); | 2682 ASSERT(args.length() == 3); |
2721 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); | 2683 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); |
2722 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2684 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
2723 } | 2685 } |
2724 | 2686 |
2725 | 2687 |
2726 void CompareNilIC::Clear(Address address, | 2688 void CompareNilIC::Clear(Address address, Code* target) { |
2727 Code* target, | |
2728 ConstantPoolArray* constant_pool) { | |
2729 if (IsCleared(target)) return; | 2689 if (IsCleared(target)) return; |
2730 ExtraICState state = target->extra_ic_state(); | 2690 ExtraICState state = target->extra_ic_state(); |
2731 | 2691 |
2732 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); | 2692 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); |
2733 stub.ClearState(); | 2693 stub.ClearState(); |
2734 | 2694 |
2735 Code* code = NULL; | 2695 Code* code = NULL; |
2736 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); | 2696 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); |
2737 | 2697 |
2738 SetTargetAtAddress(address, code, constant_pool); | 2698 SetTargetAtAddress(address, code); |
2739 } | 2699 } |
2740 | 2700 |
2741 | 2701 |
2742 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, | 2702 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, |
2743 Handle<Object> object) { | 2703 Handle<Object> object) { |
2744 if (object->IsNull() || object->IsUndefined()) { | 2704 if (object->IsNull() || object->IsUndefined()) { |
2745 return Smi::FromInt(true); | 2705 return Smi::FromInt(true); |
2746 } | 2706 } |
2747 return Smi::FromInt(object->IsUndetectableObject()); | 2707 return Smi::FromInt(object->IsUndetectableObject()); |
2748 } | 2708 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2857 #undef ADDR | 2817 #undef ADDR |
2858 }; | 2818 }; |
2859 | 2819 |
2860 | 2820 |
2861 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2821 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2862 return IC_utilities[id]; | 2822 return IC_utilities[id]; |
2863 } | 2823 } |
2864 | 2824 |
2865 | 2825 |
2866 } } // namespace v8::internal | 2826 } } // namespace v8::internal |
OLD | NEW |