| 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 5003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5014 // Load the function to call from the property through a reference. | 5014 // Load the function to call from the property through a reference. |
| 5015 | 5015 |
| 5016 // Pass receiver to called function. | 5016 // Pass receiver to called function. |
| 5017 if (property->is_synthetic()) { | 5017 if (property->is_synthetic()) { |
| 5018 Reference ref(this, property); | 5018 Reference ref(this, property); |
| 5019 ref.GetValue(); | 5019 ref.GetValue(); |
| 5020 // Use global object as receiver. | 5020 // Use global object as receiver. |
| 5021 LoadGlobalReceiver(); | 5021 LoadGlobalReceiver(); |
| 5022 } else { | 5022 } else { |
| 5023 Load(property->obj()); | 5023 Load(property->obj()); |
| 5024 frame_->Dup(); |
| 5024 Load(property->key()); | 5025 Load(property->key()); |
| 5025 Result function = EmitKeyedLoad(false); | 5026 Result function = EmitKeyedLoad(false); |
| 5026 frame_->Drop(); // Key. | |
| 5027 Result receiver = frame_->Pop(); | 5027 Result receiver = frame_->Pop(); |
| 5028 frame_->Push(&function); | 5028 frame_->Push(&function); |
| 5029 frame_->Push(&receiver); | 5029 frame_->Push(&receiver); |
| 5030 } | 5030 } |
| 5031 | 5031 |
| 5032 // Call the function. | 5032 // Call the function. |
| 5033 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); | 5033 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); |
| 5034 } | 5034 } |
| 5035 | 5035 |
| 5036 } else { | 5036 } else { |
| (...skipping 1430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6467 private: | 6467 private: |
| 6468 Label patch_site_; | 6468 Label patch_site_; |
| 6469 Register dst_; | 6469 Register dst_; |
| 6470 Register receiver_; | 6470 Register receiver_; |
| 6471 Register key_; | 6471 Register key_; |
| 6472 bool is_global_; | 6472 bool is_global_; |
| 6473 }; | 6473 }; |
| 6474 | 6474 |
| 6475 | 6475 |
| 6476 void DeferredReferenceGetKeyedValue::Generate() { | 6476 void DeferredReferenceGetKeyedValue::Generate() { |
| 6477 __ push(receiver_); // First IC argument. | 6477 if (!receiver_.is(eax)) { |
| 6478 __ push(key_); // Second IC argument. | 6478 // Register eax is available for key. |
| 6479 | 6479 if (!key_.is(eax)) { |
| 6480 __ mov(eax, key_); |
| 6481 } |
| 6482 if (!receiver_.is(edx)) { |
| 6483 __ mov(edx, receiver_); |
| 6484 } |
| 6485 } else if (!key_.is(edx)) { |
| 6486 // Register edx is available for receiver. |
| 6487 if (!receiver_.is(edx)) { |
| 6488 __ mov(edx, receiver_); |
| 6489 } |
| 6490 if (!key_.is(eax)) { |
| 6491 __ mov(eax, key_); |
| 6492 } |
| 6493 } else { |
| 6494 __ xchg(edx, eax); |
| 6495 } |
| 6480 // Calculate the delta from the IC call instruction to the map check | 6496 // Calculate the delta from the IC call instruction to the map check |
| 6481 // cmp instruction in the inlined version. This delta is stored in | 6497 // cmp instruction in the inlined version. This delta is stored in |
| 6482 // a test(eax, delta) instruction after the call so that we can find | 6498 // a test(eax, delta) instruction after the call so that we can find |
| 6483 // it in the IC initialization code and patch the cmp instruction. | 6499 // it in the IC initialization code and patch the cmp instruction. |
| 6484 // This means that we cannot allow test instructions after calls to | 6500 // This means that we cannot allow test instructions after calls to |
| 6485 // KeyedLoadIC stubs in other places. | 6501 // KeyedLoadIC stubs in other places. |
| 6486 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 6502 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 6487 RelocInfo::Mode mode = is_global_ | 6503 RelocInfo::Mode mode = is_global_ |
| 6488 ? RelocInfo::CODE_TARGET_CONTEXT | 6504 ? RelocInfo::CODE_TARGET_CONTEXT |
| 6489 : RelocInfo::CODE_TARGET; | 6505 : RelocInfo::CODE_TARGET; |
| 6490 __ call(ic, mode); | 6506 __ call(ic, mode); |
| 6491 // The delta from the start of the map-compare instruction to the | 6507 // The delta from the start of the map-compare instruction to the |
| 6492 // test instruction. We use masm_-> directly here instead of the __ | 6508 // test instruction. We use masm_-> directly here instead of the __ |
| 6493 // macro because the macro sometimes uses macro expansion to turn | 6509 // macro because the macro sometimes uses macro expansion to turn |
| 6494 // into something that can't return a value. This is encountered | 6510 // into something that can't return a value. This is encountered |
| 6495 // when doing generated code coverage tests. | 6511 // when doing generated code coverage tests. |
| 6496 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); | 6512 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); |
| 6497 // Here we use masm_-> instead of the __ macro because this is the | 6513 // Here we use masm_-> instead of the __ macro because this is the |
| 6498 // instruction that gets patched and coverage code gets in the way. | 6514 // instruction that gets patched and coverage code gets in the way. |
| 6499 masm_->test(eax, Immediate(-delta_to_patch_site)); | 6515 masm_->test(eax, Immediate(-delta_to_patch_site)); |
| 6500 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); | 6516 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); |
| 6501 | 6517 |
| 6502 if (!dst_.is(eax)) __ mov(dst_, eax); | 6518 if (!dst_.is(eax)) __ mov(dst_, eax); |
| 6503 __ pop(key_); | |
| 6504 __ pop(receiver_); | |
| 6505 } | 6519 } |
| 6506 | 6520 |
| 6507 | 6521 |
| 6508 class DeferredReferenceSetKeyedValue: public DeferredCode { | 6522 class DeferredReferenceSetKeyedValue: public DeferredCode { |
| 6509 public: | 6523 public: |
| 6510 DeferredReferenceSetKeyedValue(Register value, | 6524 DeferredReferenceSetKeyedValue(Register value, |
| 6511 Register key, | 6525 Register key, |
| 6512 Register receiver) | 6526 Register receiver) |
| 6513 : value_(value), key_(key), receiver_(receiver) { | 6527 : value_(value), key_(key), receiver_(receiver) { |
| 6514 set_comment("[ DeferredReferenceSetKeyedValue"); | 6528 set_comment("[ DeferredReferenceSetKeyedValue"); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6632 index.reg(), | 6646 index.reg(), |
| 6633 times_4, | 6647 times_4, |
| 6634 FixedArray::kHeaderSize - kHeapObjectTag)); | 6648 FixedArray::kHeaderSize - kHeapObjectTag)); |
| 6635 elements.Unuse(); | 6649 elements.Unuse(); |
| 6636 index.Unuse(); | 6650 index.Unuse(); |
| 6637 __ cmp(Operand(value.reg()), Immediate(Factory::the_hole_value())); | 6651 __ cmp(Operand(value.reg()), Immediate(Factory::the_hole_value())); |
| 6638 deferred->Branch(equal); | 6652 deferred->Branch(equal); |
| 6639 __ IncrementCounter(&Counters::keyed_load_inline, 1); | 6653 __ IncrementCounter(&Counters::keyed_load_inline, 1); |
| 6640 | 6654 |
| 6641 deferred->BindExit(); | 6655 deferred->BindExit(); |
| 6642 // Restore the receiver and key to the frame and push the | |
| 6643 // result on top of it. | |
| 6644 frame_->Push(&receiver); | |
| 6645 frame_->Push(&key); | |
| 6646 return value; | 6656 return value; |
| 6647 } else { | 6657 } else { |
| 6648 Comment cmnt(masm_, "[ Load from keyed Property"); | 6658 Comment cmnt(masm_, "[ Load from keyed Property"); |
| 6649 RelocInfo::Mode mode = is_global | 6659 RelocInfo::Mode mode = is_global |
| 6650 ? RelocInfo::CODE_TARGET_CONTEXT | 6660 ? RelocInfo::CODE_TARGET_CONTEXT |
| 6651 : RelocInfo::CODE_TARGET; | 6661 : RelocInfo::CODE_TARGET; |
| 6652 Result answer = frame_->CallKeyedLoadIC(mode); | 6662 Result answer = frame_->CallKeyedLoadIC(mode); |
| 6653 // Make sure that we do not have a test instruction after the | 6663 // Make sure that we do not have a test instruction after the |
| 6654 // call. A test instruction after the call is used to | 6664 // call. A test instruction after the call is used to |
| 6655 // indicate that we have generated an inline version of the | 6665 // indicate that we have generated an inline version of the |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6774 deferred->BindExit(); | 6784 deferred->BindExit(); |
| 6775 cgen_->frame()->Push(&value); | 6785 cgen_->frame()->Push(&value); |
| 6776 } | 6786 } |
| 6777 if (!persist_after_get_) { | 6787 if (!persist_after_get_) { |
| 6778 set_unloaded(); | 6788 set_unloaded(); |
| 6779 } | 6789 } |
| 6780 break; | 6790 break; |
| 6781 } | 6791 } |
| 6782 | 6792 |
| 6783 case KEYED: { | 6793 case KEYED: { |
| 6794 if (persist_after_get_) { |
| 6795 cgen_->frame()->PushElementAt(1); |
| 6796 cgen_->frame()->PushElementAt(1); |
| 6797 } |
| 6784 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 6798 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
| 6785 bool is_global = var != NULL; | 6799 bool is_global = var != NULL; |
| 6786 ASSERT(!is_global || var->is_global()); | 6800 ASSERT(!is_global || var->is_global()); |
| 6787 Result value = cgen_->EmitKeyedLoad(is_global); | 6801 Result value = cgen_->EmitKeyedLoad(is_global); |
| 6788 cgen_->frame()->Push(&value); | 6802 cgen_->frame()->Push(&value); |
| 6789 if (!persist_after_get_) { | 6803 if (!persist_after_get_) { |
| 6790 cgen_->UnloadReference(this); | 6804 set_unloaded(); |
| 6791 } | 6805 } |
| 6792 break; | 6806 break; |
| 6793 } | 6807 } |
| 6794 | 6808 |
| 6795 default: | 6809 default: |
| 6796 UNREACHABLE(); | 6810 UNREACHABLE(); |
| 6797 } | 6811 } |
| 6798 } | 6812 } |
| 6799 | 6813 |
| 6800 | 6814 |
| (...skipping 3820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10621 | 10635 |
| 10622 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 10636 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 10623 // tagged as a small integer. | 10637 // tagged as a small integer. |
| 10624 __ bind(&runtime); | 10638 __ bind(&runtime); |
| 10625 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); | 10639 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); |
| 10626 } | 10640 } |
| 10627 | 10641 |
| 10628 #undef __ | 10642 #undef __ |
| 10629 | 10643 |
| 10630 } } // namespace v8::internal | 10644 } } // namespace v8::internal |
| OLD | NEW |