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 5397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5408 : RelocInfo::CODE_TARGET; | 5408 : RelocInfo::CODE_TARGET; |
5409 Result answer = cgen_->frame()->CallLoadIC(mode); | 5409 Result answer = cgen_->frame()->CallLoadIC(mode); |
5410 // A test eax instruction following the call signals that the | 5410 // A test eax instruction following the call signals that the |
5411 // inobject property case was inlined. Ensure that there is not | 5411 // inobject property case was inlined. Ensure that there is not |
5412 // a test eax instruction here. | 5412 // a test eax instruction here. |
5413 __ nop(); | 5413 __ nop(); |
5414 cgen_->frame()->Push(&answer); | 5414 cgen_->frame()->Push(&answer); |
5415 } else { | 5415 } else { |
5416 // Inline the inobject property case. | 5416 // Inline the inobject property case. |
5417 Comment cmnt(masm, "[ Inlined named property load"); | 5417 Comment cmnt(masm, "[ Inlined named property load"); |
| 5418 DeferredReferenceGetNamedValue* deferred = |
| 5419 new DeferredReferenceGetNamedValue(cgen_, GetName()); |
5418 Result receiver = cgen_->frame()->Pop(); | 5420 Result receiver = cgen_->frame()->Pop(); |
5419 receiver.ToRegister(); | 5421 receiver.ToRegister(); |
5420 | 5422 |
5421 // Preallocate the value register to ensure that there is no | 5423 // Try to preallocate the value register so that all frames |
5422 // spill emitted between the patch site label and the offset in | 5424 // reaching the deferred code are identical. |
5423 // the load instruction and that all frames reaching the | 5425 Result value = cgen_->allocator()->AllocateWithoutSpilling(); |
5424 // deferred code are identical. | |
5425 Result value = cgen_->allocator()->Allocate(); | |
5426 ASSERT(value.is_valid()); | |
5427 | 5426 |
5428 // Check that the receiver is a heap object. | 5427 // Check that the receiver is a heap object. |
5429 __ test(receiver.reg(), Immediate(kSmiTagMask)); | 5428 __ test(receiver.reg(), Immediate(kSmiTagMask)); |
5430 | 5429 |
5431 DeferredReferenceGetNamedValue* deferred = | 5430 if (value.is_valid()) deferred->SetEntryFrame(&receiver); |
5432 new DeferredReferenceGetNamedValue(cgen_, GetName()); | |
5433 deferred->SetEntryFrame(&receiver); | |
5434 deferred->enter()->Branch(zero, &receiver, not_taken); | 5431 deferred->enter()->Branch(zero, &receiver, not_taken); |
5435 | 5432 |
| 5433 // Do not allocate the value register after binding the patch |
| 5434 // site label. The distance from the patch site to the offset |
| 5435 // must be constant. |
| 5436 if (!value.is_valid()) { |
| 5437 value = cgen_->allocator()->Allocate(); |
| 5438 ASSERT(value.is_valid()); |
| 5439 } |
| 5440 |
5436 __ bind(deferred->patch_site()); | 5441 __ bind(deferred->patch_site()); |
5437 // This is the map check instruction that will be patched (so we can't | 5442 // This is the map check instruction that will be patched (so we can't |
5438 // use the double underscore macro that may insert instructions). | 5443 // use the double underscore macro that may insert instructions). |
5439 // Initially use an invalid map to force a failure. | 5444 // Initially use an invalid map to force a failure. |
5440 masm->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset), | 5445 masm->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset), |
5441 Immediate(Factory::null_value())); | 5446 Immediate(Factory::null_value())); |
5442 // This branch is always a forwards branch so it's always a fixed | 5447 // This branch is always a forwards branch so it's always a fixed |
5443 // size which allows the assert below to succeed and patching to work. | 5448 // size which allows the assert below to succeed and patching to work. |
5444 deferred->enter()->Branch(not_equal, &receiver, not_taken); | 5449 deferred->enter()->Branch(not_equal, &receiver, not_taken); |
5445 | 5450 |
(...skipping 29 matching lines...) Expand all Loading... |
5475 if (cgen_->loop_nesting() > 0) { | 5480 if (cgen_->loop_nesting() > 0) { |
5476 Comment cmnt(masm, "[ Inlined array index load"); | 5481 Comment cmnt(masm, "[ Inlined array index load"); |
5477 DeferredReferenceGetKeyedValue* deferred = | 5482 DeferredReferenceGetKeyedValue* deferred = |
5478 new DeferredReferenceGetKeyedValue(cgen_, is_global); | 5483 new DeferredReferenceGetKeyedValue(cgen_, is_global); |
5479 | 5484 |
5480 Result key = cgen_->frame()->Pop(); | 5485 Result key = cgen_->frame()->Pop(); |
5481 Result receiver = cgen_->frame()->Pop(); | 5486 Result receiver = cgen_->frame()->Pop(); |
5482 key.ToRegister(); | 5487 key.ToRegister(); |
5483 receiver.ToRegister(); | 5488 receiver.ToRegister(); |
5484 | 5489 |
| 5490 // Try to preallocate the elements and index scratch registers |
| 5491 // so that all frames reaching the deferred code are identical. |
| 5492 Result elements = cgen_->allocator()->AllocateWithoutSpilling(); |
| 5493 Result index = cgen_->allocator()->AllocateWithoutSpilling(); |
| 5494 if (elements.is_valid() && index.is_valid()) { |
| 5495 deferred->SetEntryFrame(&receiver, &key); |
| 5496 } |
| 5497 |
5485 // Check that the receiver is not a smi (only needed if this | 5498 // Check that the receiver is not a smi (only needed if this |
5486 // is not a load from the global context) and that it has the | 5499 // is not a load from the global context) and that it has the |
5487 // expected map. | 5500 // expected map. |
5488 if (!is_global) { | 5501 if (!is_global) { |
5489 __ test(receiver.reg(), Immediate(kSmiTagMask)); | 5502 __ test(receiver.reg(), Immediate(kSmiTagMask)); |
5490 deferred->enter()->Branch(zero, &receiver, &key, not_taken); | 5503 deferred->enter()->Branch(zero, &receiver, &key, not_taken); |
5491 } | 5504 } |
5492 | 5505 |
5493 // Initially, use an invalid map. The map is patched in the IC | 5506 // Initially, use an invalid map. The map is patched in the IC |
5494 // initialization code. | 5507 // initialization code. |
5495 __ bind(deferred->patch_site()); | 5508 __ bind(deferred->patch_site()); |
5496 // Use masm-> here instead of the double underscore macro since extra | 5509 // Use masm-> here instead of the double underscore macro since extra |
5497 // coverage code can interfere with the patching. | 5510 // coverage code can interfere with the patching. |
5498 masm->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset), | 5511 masm->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset), |
5499 Immediate(Factory::null_value())); | 5512 Immediate(Factory::null_value())); |
5500 deferred->enter()->Branch(not_equal, &receiver, &key, not_taken); | 5513 deferred->enter()->Branch(not_equal, &receiver, &key, not_taken); |
5501 | 5514 |
5502 // Check that the key is a smi. | 5515 // Check that the key is a smi. |
5503 __ test(key.reg(), Immediate(kSmiTagMask)); | 5516 __ test(key.reg(), Immediate(kSmiTagMask)); |
5504 deferred->enter()->Branch(not_zero, &receiver, &key, not_taken); | 5517 deferred->enter()->Branch(not_zero, &receiver, &key, not_taken); |
5505 | 5518 |
5506 // Get the elements array from the receiver and check that it | 5519 // Get the elements array from the receiver and check that it |
5507 // is not a dictionary. | 5520 // is not a dictionary. |
5508 Result elements = cgen_->allocator()->Allocate(); | 5521 if (!elements.is_valid()) { |
5509 ASSERT(elements.is_valid()); | 5522 elements = cgen_->allocator()->Allocate(); |
| 5523 ASSERT(elements.is_valid()); |
| 5524 } |
5510 __ mov(elements.reg(), | 5525 __ mov(elements.reg(), |
5511 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); | 5526 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); |
5512 __ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset), | 5527 __ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset), |
5513 Immediate(Factory::hash_table_map())); | 5528 Immediate(Factory::hash_table_map())); |
5514 deferred->enter()->Branch(equal, &receiver, &key, not_taken); | 5529 deferred->enter()->Branch(equal, &receiver, &key, not_taken); |
5515 | 5530 |
5516 // Shift the key to get the actual index value and check that | 5531 // Shift the key to get the actual index value and check that |
5517 // it is within bounds. | 5532 // it is within bounds. |
5518 Result index = cgen_->allocator()->Allocate(); | 5533 if (!index.is_valid()) { |
5519 ASSERT(index.is_valid()); | 5534 index = cgen_->allocator()->Allocate(); |
| 5535 ASSERT(index.is_valid()); |
| 5536 } |
5520 __ mov(index.reg(), key.reg()); | 5537 __ mov(index.reg(), key.reg()); |
5521 __ sar(index.reg(), kSmiTagSize); | 5538 __ sar(index.reg(), kSmiTagSize); |
5522 __ cmp(index.reg(), | 5539 __ cmp(index.reg(), |
5523 FieldOperand(elements.reg(), Array::kLengthOffset)); | 5540 FieldOperand(elements.reg(), Array::kLengthOffset)); |
5524 deferred->enter()->Branch(above_equal, &receiver, &key, not_taken); | 5541 deferred->enter()->Branch(above_equal, &receiver, &key, not_taken); |
5525 | 5542 |
5526 // Load and check that the result is not the hole. We could | 5543 // Load and check that the result is not the hole. We could |
5527 // reuse the index or elements register for the value. | 5544 // reuse the index or elements register for the value. |
5528 // | 5545 // |
5529 // TODO(206): Consider whether it makes sense to try some | 5546 // TODO(206): Consider whether it makes sense to try some |
(...skipping 1708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7238 | 7255 |
7239 // Slow-case: Go through the JavaScript implementation. | 7256 // Slow-case: Go through the JavaScript implementation. |
7240 __ bind(&slow); | 7257 __ bind(&slow); |
7241 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 7258 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
7242 } | 7259 } |
7243 | 7260 |
7244 | 7261 |
7245 #undef __ | 7262 #undef __ |
7246 | 7263 |
7247 } } // namespace v8::internal | 7264 } } // namespace v8::internal |
OLD | NEW |