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