OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 9131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9142 // dst. | 9142 // dst. |
9143 class DeferredReferenceGetNamedValue: public DeferredCode { | 9143 class DeferredReferenceGetNamedValue: public DeferredCode { |
9144 public: | 9144 public: |
9145 DeferredReferenceGetNamedValue(Register dst, | 9145 DeferredReferenceGetNamedValue(Register dst, |
9146 Register receiver, | 9146 Register receiver, |
9147 Handle<String> name, | 9147 Handle<String> name, |
9148 bool is_contextual) | 9148 bool is_contextual) |
9149 : dst_(dst), | 9149 : dst_(dst), |
9150 receiver_(receiver), | 9150 receiver_(receiver), |
9151 name_(name), | 9151 name_(name), |
9152 is_contextual_(is_contextual) { | 9152 is_contextual_(is_contextual), |
| 9153 is_dont_delete_(false) { |
9153 set_comment(is_contextual | 9154 set_comment(is_contextual |
9154 ? "[ DeferredReferenceGetNamedValue (contextual)" | 9155 ? "[ DeferredReferenceGetNamedValue (contextual)" |
9155 : "[ DeferredReferenceGetNamedValue"); | 9156 : "[ DeferredReferenceGetNamedValue"); |
9156 } | 9157 } |
9157 | 9158 |
9158 virtual void Generate(); | 9159 virtual void Generate(); |
9159 | 9160 |
9160 Label* patch_site() { return &patch_site_; } | 9161 Label* patch_site() { return &patch_site_; } |
9161 | 9162 |
| 9163 void set_is_dont_delete(bool value) { |
| 9164 ASSERT(is_contextual_); |
| 9165 is_dont_delete_ = value; |
| 9166 } |
| 9167 |
9162 private: | 9168 private: |
9163 Label patch_site_; | 9169 Label patch_site_; |
9164 Register dst_; | 9170 Register dst_; |
9165 Register receiver_; | 9171 Register receiver_; |
9166 Handle<String> name_; | 9172 Handle<String> name_; |
9167 bool is_contextual_; | 9173 bool is_contextual_; |
| 9174 bool is_dont_delete_; |
9168 }; | 9175 }; |
9169 | 9176 |
9170 | 9177 |
9171 void DeferredReferenceGetNamedValue::Generate() { | 9178 void DeferredReferenceGetNamedValue::Generate() { |
9172 if (!receiver_.is(eax)) { | 9179 if (!receiver_.is(eax)) { |
9173 __ mov(eax, receiver_); | 9180 __ mov(eax, receiver_); |
9174 } | 9181 } |
9175 __ Set(ecx, Immediate(name_)); | 9182 __ Set(ecx, Immediate(name_)); |
9176 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 9183 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
9177 RelocInfo::Mode mode = is_contextual_ | 9184 RelocInfo::Mode mode = is_contextual_ |
9178 ? RelocInfo::CODE_TARGET_CONTEXT | 9185 ? RelocInfo::CODE_TARGET_CONTEXT |
9179 : RelocInfo::CODE_TARGET; | 9186 : RelocInfo::CODE_TARGET; |
9180 __ call(ic, mode); | 9187 __ call(ic, mode); |
9181 // The call must be followed by: | 9188 // The call must be followed by: |
9182 // - a test eax instruction to indicate that the inobject property | 9189 // - a test eax instruction to indicate that the inobject property |
9183 // case was inlined. | 9190 // case was inlined. |
9184 // - a mov ecx instruction to indicate that the contextual property | 9191 // - a mov ecx or mov edx instruction to indicate that the |
9185 // load was inlined. | 9192 // contextual property load was inlined. |
9186 // | 9193 // |
9187 // Store the delta to the map check instruction here in the test | 9194 // Store the delta to the map check instruction here in the test |
9188 // instruction. Use masm_-> instead of the __ macro since the | 9195 // instruction. Use masm_-> instead of the __ macro since the |
9189 // latter can't return a value. | 9196 // latter can't return a value. |
9190 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); | 9197 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); |
9191 // Here we use masm_-> instead of the __ macro because this is the | 9198 // Here we use masm_-> instead of the __ macro because this is the |
9192 // instruction that gets patched and coverage code gets in the way. | 9199 // instruction that gets patched and coverage code gets in the way. |
9193 if (is_contextual_) { | 9200 if (is_contextual_) { |
9194 masm_->mov(ecx, -delta_to_patch_site); | 9201 masm_->mov(is_dont_delete_ ? edx : ecx, -delta_to_patch_site); |
9195 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1); | 9202 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1); |
| 9203 if (is_dont_delete_) { |
| 9204 __ IncrementCounter(&Counters::dont_delete_hint_miss, 1); |
| 9205 } |
9196 } else { | 9206 } else { |
9197 masm_->test(eax, Immediate(-delta_to_patch_site)); | 9207 masm_->test(eax, Immediate(-delta_to_patch_site)); |
9198 __ IncrementCounter(&Counters::named_load_inline_miss, 1); | 9208 __ IncrementCounter(&Counters::named_load_inline_miss, 1); |
9199 } | 9209 } |
9200 | 9210 |
9201 if (!dst_.is(eax)) __ mov(dst_, eax); | 9211 if (!dst_.is(eax)) __ mov(dst_, eax); |
9202 } | 9212 } |
9203 | 9213 |
9204 | 9214 |
9205 class DeferredReferenceGetKeyedValue: public DeferredCode { | 9215 class DeferredReferenceGetKeyedValue: public DeferredCode { |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9429 if (is_contextual) { | 9439 if (is_contextual) { |
9430 // Load the (initialy invalid) cell and get its value. | 9440 // Load the (initialy invalid) cell and get its value. |
9431 masm()->mov(result.reg(), Factory::null_value()); | 9441 masm()->mov(result.reg(), Factory::null_value()); |
9432 if (FLAG_debug_code) { | 9442 if (FLAG_debug_code) { |
9433 __ cmp(FieldOperand(result.reg(), HeapObject::kMapOffset), | 9443 __ cmp(FieldOperand(result.reg(), HeapObject::kMapOffset), |
9434 Factory::global_property_cell_map()); | 9444 Factory::global_property_cell_map()); |
9435 __ Assert(equal, "Uninitialized inlined contextual load"); | 9445 __ Assert(equal, "Uninitialized inlined contextual load"); |
9436 } | 9446 } |
9437 __ mov(result.reg(), | 9447 __ mov(result.reg(), |
9438 FieldOperand(result.reg(), JSGlobalPropertyCell::kValueOffset)); | 9448 FieldOperand(result.reg(), JSGlobalPropertyCell::kValueOffset)); |
9439 __ cmp(result.reg(), Factory::the_hole_value()); | 9449 bool is_dont_delete = false; |
9440 deferred->Branch(equal); | 9450 if (!info_->closure().is_null()) { |
| 9451 // When doing lazy compilation we can check if the global cell |
| 9452 // already exists and use its "don't delete" status as a hint. |
| 9453 AssertNoAllocation no_gc; |
| 9454 v8::internal::GlobalObject* global_object = |
| 9455 info_->closure()->context()->global(); |
| 9456 LookupResult lookup; |
| 9457 global_object->LocalLookupRealNamedProperty(*name, &lookup); |
| 9458 if (lookup.IsProperty() && lookup.type() == NORMAL) { |
| 9459 ASSERT(lookup.holder() == global_object); |
| 9460 ASSERT(global_object->property_dictionary()->ValueAt( |
| 9461 lookup.GetDictionaryEntry())->IsJSGlobalPropertyCell()); |
| 9462 is_dont_delete = lookup.IsDontDelete(); |
| 9463 } |
| 9464 } |
| 9465 deferred->set_is_dont_delete(is_dont_delete); |
| 9466 if (!is_dont_delete) { |
| 9467 __ cmp(result.reg(), Factory::the_hole_value()); |
| 9468 deferred->Branch(equal); |
| 9469 } else if (FLAG_debug_code) { |
| 9470 __ cmp(result.reg(), Factory::the_hole_value()); |
| 9471 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 9472 } |
9441 __ IncrementCounter(&Counters::named_load_global_inline, 1); | 9473 __ IncrementCounter(&Counters::named_load_global_inline, 1); |
| 9474 if (is_dont_delete) { |
| 9475 __ IncrementCounter(&Counters::dont_delete_hint_hit, 1); |
| 9476 } |
9442 } else { | 9477 } else { |
9443 // The initial (invalid) offset has to be large enough to force a 32-bit | 9478 // The initial (invalid) offset has to be large enough to force a 32-bit |
9444 // instruction encoding to allow patching with an arbitrary offset. Use | 9479 // instruction encoding to allow patching with an arbitrary offset. Use |
9445 // kMaxInt (minus kHeapObjectTag). | 9480 // kMaxInt (minus kHeapObjectTag). |
9446 int offset = kMaxInt; | 9481 int offset = kMaxInt; |
9447 masm()->mov(result.reg(), FieldOperand(receiver.reg(), offset)); | 9482 masm()->mov(result.reg(), FieldOperand(receiver.reg(), offset)); |
9448 __ IncrementCounter(&Counters::named_load_inline, 1); | 9483 __ IncrementCounter(&Counters::named_load_inline, 1); |
9449 } | 9484 } |
9450 | 9485 |
9451 deferred->BindExit(); | 9486 deferred->BindExit(); |
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10101 masm.GetCode(&desc); | 10136 masm.GetCode(&desc); |
10102 // Call the function from C++. | 10137 // Call the function from C++. |
10103 return FUNCTION_CAST<MemCopyFunction>(buffer); | 10138 return FUNCTION_CAST<MemCopyFunction>(buffer); |
10104 } | 10139 } |
10105 | 10140 |
10106 #undef __ | 10141 #undef __ |
10107 | 10142 |
10108 } } // namespace v8::internal | 10143 } } // namespace v8::internal |
10109 | 10144 |
10110 #endif // V8_TARGET_ARCH_IA32 | 10145 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |