| 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 |