OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "bootstrapper.h" | 30 #include "bootstrapper.h" |
31 #include "codegen-inl.h" | 31 #include "codegen-inl.h" |
32 #include "debug.h" | 32 #include "debug.h" |
| 33 #include "ic-inl.h" |
33 #include "parser.h" | 34 #include "parser.h" |
34 #include "register-allocator-inl.h" | 35 #include "register-allocator-inl.h" |
35 #include "runtime.h" | 36 #include "runtime.h" |
36 #include "scopes.h" | 37 #include "scopes.h" |
37 | 38 |
38 namespace v8 { namespace internal { | 39 namespace v8 { namespace internal { |
39 | 40 |
40 #define __ ACCESS_MASM(masm_) | 41 #define __ ACCESS_MASM(masm_) |
41 | 42 |
42 // ------------------------------------------------------------------------- | 43 // ------------------------------------------------------------------------- |
(...skipping 3360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3403 tmp.Unuse(); | 3404 tmp.Unuse(); |
3404 | 3405 |
3405 // All extension objects were empty and it is safe to use a global | 3406 // All extension objects were empty and it is safe to use a global |
3406 // load IC call. | 3407 // load IC call. |
3407 LoadGlobal(); | 3408 LoadGlobal(); |
3408 frame_->Push(slot->var()->name()); | 3409 frame_->Push(slot->var()->name()); |
3409 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 3410 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
3410 ? RelocInfo::CODE_TARGET | 3411 ? RelocInfo::CODE_TARGET |
3411 : RelocInfo::CODE_TARGET_CONTEXT; | 3412 : RelocInfo::CODE_TARGET_CONTEXT; |
3412 Result answer = frame_->CallLoadIC(mode); | 3413 Result answer = frame_->CallLoadIC(mode); |
3413 | 3414 // A test eax instruction following the call signals that the inobject |
| 3415 // property case was inlined. Ensure that there is not a test eax |
| 3416 // instruction here. |
| 3417 __ nop(); |
3414 // Discard the global object. The result is in answer. | 3418 // Discard the global object. The result is in answer. |
3415 frame_->Drop(); | 3419 frame_->Drop(); |
3416 return answer; | 3420 return answer; |
3417 } | 3421 } |
3418 | 3422 |
3419 | 3423 |
3420 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { | 3424 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { |
3421 if (slot->type() == Slot::LOOKUP) { | 3425 if (slot->type() == Slot::LOOKUP) { |
3422 ASSERT(slot->var()->is_dynamic()); | 3426 ASSERT(slot->var()->is_dynamic()); |
3423 | 3427 |
(...skipping 1802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5226 bool CodeGenerator::HasValidEntryRegisters() { | 5230 bool CodeGenerator::HasValidEntryRegisters() { |
5227 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0)) | 5231 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0)) |
5228 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) | 5232 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) |
5229 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) | 5233 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) |
5230 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0)) | 5234 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0)) |
5231 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0)); | 5235 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0)); |
5232 } | 5236 } |
5233 #endif | 5237 #endif |
5234 | 5238 |
5235 | 5239 |
| 5240 class DeferredReferenceGetNamedValue: public DeferredCode { |
| 5241 public: |
| 5242 DeferredReferenceGetNamedValue(CodeGenerator* cgen, Handle<String> name) |
| 5243 : DeferredCode(cgen), name_(name) { |
| 5244 set_comment("[ DeferredReferenceGetNamedValue"); |
| 5245 } |
| 5246 |
| 5247 virtual void Generate(); |
| 5248 |
| 5249 Label* patch_site() { return &patch_site_; } |
| 5250 |
| 5251 private: |
| 5252 Label patch_site_; |
| 5253 Handle<String> name_; |
| 5254 }; |
| 5255 |
| 5256 |
| 5257 void DeferredReferenceGetNamedValue::Generate() { |
| 5258 CodeGenerator* cgen = generator(); |
| 5259 Result receiver(cgen); |
| 5260 enter()->Bind(&receiver); |
| 5261 |
| 5262 cgen->frame()->Push(&receiver); |
| 5263 cgen->frame()->Push(name_); |
| 5264 Result answer = cgen->frame()->CallLoadIC(RelocInfo::CODE_TARGET); |
| 5265 // The call must be followed by a test eax instruction to indicate |
| 5266 // that the inobject property case was inlined. |
| 5267 ASSERT(answer.is_register() && answer.reg().is(eax)); |
| 5268 // Store the delta to the map check instruction here in the test |
| 5269 // instruction. |
| 5270 int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site()); |
| 5271 // Here we use masm_-> instead of the double underscore macro because |
| 5272 // this is the instruction that gets patched and coverage code gets in |
| 5273 // the way. |
| 5274 masm_->test(answer.reg(), Immediate(-delta_to_patch_site)); |
| 5275 __ IncrementCounter(&Counters::named_load_inline_miss, 1); |
| 5276 receiver = cgen->frame()->Pop(); |
| 5277 exit_.Jump(&receiver, &answer); |
| 5278 } |
| 5279 |
| 5280 |
5236 class DeferredReferenceGetKeyedValue: public DeferredCode { | 5281 class DeferredReferenceGetKeyedValue: public DeferredCode { |
5237 public: | 5282 public: |
5238 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global) | 5283 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global) |
5239 : DeferredCode(generator), is_global_(is_global) { | 5284 : DeferredCode(generator), is_global_(is_global) { |
5240 set_comment("[ DeferredReferenceGetKeyedValue"); | 5285 set_comment("[ DeferredReferenceGetKeyedValue"); |
5241 } | 5286 } |
5242 | 5287 |
5243 virtual void Generate(); | 5288 virtual void Generate(); |
5244 | 5289 |
5245 Label* patch_site() { return &patch_site_; } | 5290 Label* patch_site() { return &patch_site_; } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5327 break; | 5372 break; |
5328 } | 5373 } |
5329 | 5374 |
5330 case NAMED: { | 5375 case NAMED: { |
5331 // TODO(1241834): Make sure that it is safe to ignore the | 5376 // TODO(1241834): Make sure that it is safe to ignore the |
5332 // distinction between expressions in a typeof and not in a | 5377 // distinction between expressions in a typeof and not in a |
5333 // typeof. If there is a chance that reference errors can be | 5378 // typeof. If there is a chance that reference errors can be |
5334 // thrown below, we must distinguish between the two kinds of | 5379 // thrown below, we must distinguish between the two kinds of |
5335 // loads (typeof expression loads must not throw a reference | 5380 // loads (typeof expression loads must not throw a reference |
5336 // error). | 5381 // error). |
5337 Comment cmnt(masm, "[ Load from named Property"); | 5382 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
5338 cgen_->frame()->Push(GetName()); | 5383 bool is_global = var != NULL; |
| 5384 ASSERT(!is_global || var->is_global()); |
5339 | 5385 |
5340 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 5386 if (is_global || cgen_->scope()->is_global_scope()) { |
5341 ASSERT(var == NULL || var->is_global()); | 5387 // Do not inline the inobject property case for loads from the |
5342 RelocInfo::Mode mode = (var == NULL) | 5388 // global object or loads in toplevel code. |
5343 ? RelocInfo::CODE_TARGET | 5389 Comment cmnt(masm, "[ Load from named Property"); |
5344 : RelocInfo::CODE_TARGET_CONTEXT; | 5390 cgen_->frame()->Push(GetName()); |
5345 Result answer = cgen_->frame()->CallLoadIC(mode); | 5391 |
5346 cgen_->frame()->Push(&answer); | 5392 RelocInfo::Mode mode = is_global |
| 5393 ? RelocInfo::CODE_TARGET_CONTEXT |
| 5394 : RelocInfo::CODE_TARGET; |
| 5395 Result answer = cgen_->frame()->CallLoadIC(mode); |
| 5396 // A test eax instruction following the call signals that the |
| 5397 // inobject property case was inlined. Ensure that there is not |
| 5398 // a test eax instruction here. |
| 5399 __ nop(); |
| 5400 cgen_->frame()->Push(&answer); |
| 5401 } else { |
| 5402 // Inline the inobject property case. |
| 5403 Comment cmnt(masm, "[ Inlined named property load"); |
| 5404 DeferredReferenceGetNamedValue* deferred = |
| 5405 new DeferredReferenceGetNamedValue(cgen_, GetName()); |
| 5406 Result receiver = cgen_->frame()->Pop(); |
| 5407 receiver.ToRegister(); |
| 5408 // Check that the receiver is a heap object. |
| 5409 __ test(receiver.reg(), Immediate(kSmiTagMask)); |
| 5410 deferred->enter()->Branch(zero, &receiver, not_taken); |
| 5411 |
| 5412 // Preallocate the value register to ensure that there is no |
| 5413 // spill emitted between the patch site label and the offset in |
| 5414 // the load instruction. |
| 5415 Result value = cgen_->allocator()->Allocate(); |
| 5416 ASSERT(value.is_valid()); |
| 5417 __ bind(deferred->patch_site()); |
| 5418 // This is the map chack instruction that will be patched. |
| 5419 // Initially use an invalid map to force a failure. |
| 5420 __ cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset), |
| 5421 Immediate(Factory::null_value())); |
| 5422 deferred->enter()->Branch(not_equal, &receiver, not_taken); |
| 5423 |
| 5424 // The delta from the patch label to the load offset must be |
| 5425 // statically known. |
| 5426 ASSERT(masm->SizeOfCodeGeneratedSince(deferred->patch_site()) == |
| 5427 LoadIC::kOffsetToLoadInstruction); |
| 5428 // The initial (invalid) offset has to be large enough to force |
| 5429 // a 32-bit instruction encoding to allow patching with an |
| 5430 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag). |
| 5431 int offset = kMaxInt; |
| 5432 __ mov(value.reg(), FieldOperand(receiver.reg(), offset)); |
| 5433 |
| 5434 __ IncrementCounter(&Counters::named_load_inline, 1); |
| 5435 deferred->BindExit(&receiver, &value); |
| 5436 cgen_->frame()->Push(&receiver); |
| 5437 cgen_->frame()->Push(&value); |
| 5438 } |
5347 break; | 5439 break; |
5348 } | 5440 } |
5349 | 5441 |
5350 case KEYED: { | 5442 case KEYED: { |
5351 // TODO(1241834): Make sure that this it is safe to ignore the | 5443 // TODO(1241834): Make sure that this it is safe to ignore the |
5352 // distinction between expressions in a typeof and not in a typeof. | 5444 // distinction between expressions in a typeof and not in a typeof. |
5353 Comment cmnt(masm, "[ Load from keyed Property"); | 5445 Comment cmnt(masm, "[ Load from keyed Property"); |
5354 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 5446 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
5355 bool is_global = var != NULL; | 5447 bool is_global = var != NULL; |
5356 ASSERT(!is_global || var->is_global()); | 5448 ASSERT(!is_global || var->is_global()); |
(...skipping 1764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7121 | 7213 |
7122 // Slow-case: Go through the JavaScript implementation. | 7214 // Slow-case: Go through the JavaScript implementation. |
7123 __ bind(&slow); | 7215 __ bind(&slow); |
7124 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 7216 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
7125 } | 7217 } |
7126 | 7218 |
7127 | 7219 |
7128 #undef __ | 7220 #undef __ |
7129 | 7221 |
7130 } } // namespace v8::internal | 7222 } } // namespace v8::internal |
OLD | NEW |