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 5731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5742 public: | 5742 public: |
5743 DeferredReferenceSetKeyedValue(Register value, | 5743 DeferredReferenceSetKeyedValue(Register value, |
5744 Register key, | 5744 Register key, |
5745 Register receiver) | 5745 Register receiver) |
5746 : value_(value), key_(key), receiver_(receiver) { | 5746 : value_(value), key_(key), receiver_(receiver) { |
5747 set_comment("[ DeferredReferenceSetKeyedValue"); | 5747 set_comment("[ DeferredReferenceSetKeyedValue"); |
5748 } | 5748 } |
5749 | 5749 |
5750 virtual void Generate(); | 5750 virtual void Generate(); |
5751 | 5751 |
5752 Label* patch_site() { return &patch_site_; } | |
5753 | |
5752 private: | 5754 private: |
5753 Register value_; | 5755 Register value_; |
5754 Register key_; | 5756 Register key_; |
5755 Register receiver_; | 5757 Register receiver_; |
5758 Label patch_site_; | |
5756 }; | 5759 }; |
5757 | 5760 |
5758 | 5761 |
5759 void DeferredReferenceSetKeyedValue::Generate() { | 5762 void DeferredReferenceSetKeyedValue::Generate() { |
5760 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); | 5763 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); |
5761 // Push receiver and key arguments on the stack. | 5764 // Push receiver and key arguments on the stack. |
5762 __ push(receiver_); | 5765 __ push(receiver_); |
5763 __ push(key_); | 5766 __ push(key_); |
5764 // Move value argument to eax as expected by the IC stub. | 5767 // Move value argument to eax as expected by the IC stub. |
5765 if (!value_.is(eax)) __ mov(eax, value_); | 5768 if (!value_.is(eax)) __ mov(eax, value_); |
5766 // Call the IC stub. | 5769 // Call the IC stub. |
5767 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 5770 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
5768 __ call(ic, RelocInfo::CODE_TARGET); | 5771 __ call(ic, RelocInfo::CODE_TARGET); |
5772 // The delta from the start of the map-compare instruction to the | |
5773 // test instruction. We use masm_-> directly here instead of the | |
5774 // __ macro because the macro sometimes uses macro expansion to turn | |
5775 // into something that can't return a value. This is encountered | |
5776 // when doing generated code coverage tests. | |
5777 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); | |
5778 // Here we use masm_-> instead of the __ macro because this is the | |
Søren Thygesen Gjesse
2009/06/12 11:15:29
Maybe loose this comment as it is already in the c
| |
5779 // instruction that gets patched and coverage code gets in the way. | |
5780 masm_->test(eax, Immediate(-delta_to_patch_site)); | |
5769 // Restore value (returned from store IC), key and receiver | 5781 // Restore value (returned from store IC), key and receiver |
5770 // registers. | 5782 // registers. |
5771 if (!value_.is(eax)) __ mov(value_, eax); | 5783 if (!value_.is(eax)) __ mov(value_, eax); |
5772 __ pop(key_); | 5784 __ pop(key_); |
5773 __ pop(receiver_); | 5785 __ pop(receiver_); |
5774 } | 5786 } |
5775 | 5787 |
5776 | 5788 |
5777 #undef __ | 5789 #undef __ |
5778 #define __ ACCESS_MASM(masm) | 5790 #define __ ACCESS_MASM(masm) |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6115 // Check that the key is within bounds. Both the key and the | 6127 // Check that the key is within bounds. Both the key and the |
6116 // length of the JSArray are smis. | 6128 // length of the JSArray are smis. |
6117 __ cmp(key.reg(), | 6129 __ cmp(key.reg(), |
6118 FieldOperand(receiver.reg(), JSArray::kLengthOffset)); | 6130 FieldOperand(receiver.reg(), JSArray::kLengthOffset)); |
6119 deferred->Branch(greater_equal); | 6131 deferred->Branch(greater_equal); |
6120 | 6132 |
6121 // Get the elements array from the receiver and check that it | 6133 // Get the elements array from the receiver and check that it |
6122 // is not a dictionary. | 6134 // is not a dictionary. |
6123 __ mov(tmp.reg(), | 6135 __ mov(tmp.reg(), |
6124 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); | 6136 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); |
6137 // Bind the deferred code patch site to be able to locate the | |
6138 // fixed array map comparison. When debugging, we patch this | |
6139 // comparison to always fail so that we will hit the IC call | |
6140 // in the deferred code which will allow the debugger to | |
6141 // break for fast case stores. | |
6142 __ bind(deferred->patch_site()); | |
6125 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset), | 6143 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset), |
6126 Immediate(Factory::hash_table_map())); | 6144 Immediate(Factory::fixed_array_map())); |
6127 deferred->Branch(equal); | 6145 deferred->Branch(not_equal); |
6128 | 6146 |
6129 // Store the value. | 6147 // Store the value. |
6130 __ mov(Operand(tmp.reg(), | 6148 __ mov(Operand(tmp.reg(), |
6131 key.reg(), | 6149 key.reg(), |
6132 times_2, | 6150 times_2, |
6133 Array::kHeaderSize - kHeapObjectTag), | 6151 Array::kHeaderSize - kHeapObjectTag), |
6134 value.reg()); | 6152 value.reg()); |
6135 __ IncrementCounter(&Counters::keyed_store_inline, 1); | 6153 __ IncrementCounter(&Counters::keyed_store_inline, 1); |
6136 | 6154 |
6137 deferred->BindExit(); | 6155 deferred->BindExit(); |
6138 | 6156 |
6139 cgen_->frame()->Push(&receiver); | 6157 cgen_->frame()->Push(&receiver); |
6140 cgen_->frame()->Push(&key); | 6158 cgen_->frame()->Push(&key); |
6141 cgen_->frame()->Push(&value); | 6159 cgen_->frame()->Push(&value); |
6142 } else { | 6160 } else { |
6143 Result answer = cgen_->frame()->CallKeyedStoreIC(); | 6161 Result answer = cgen_->frame()->CallKeyedStoreIC(); |
6162 // Make sure that we do not have a test instruction after the | |
6163 // call. A test instruction after the call is used to | |
6164 // indicate that we have generated an inline version of the | |
6165 // keyed store. | |
6166 __ nop(); | |
6144 cgen_->frame()->Push(&answer); | 6167 cgen_->frame()->Push(&answer); |
6145 } | 6168 } |
6146 break; | 6169 break; |
6147 } | 6170 } |
6148 | 6171 |
6149 default: | 6172 default: |
6150 UNREACHABLE(); | 6173 UNREACHABLE(); |
6151 } | 6174 } |
6152 } | 6175 } |
6153 | 6176 |
(...skipping 1300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7454 | 7477 |
7455 // Slow-case: Go through the JavaScript implementation. | 7478 // Slow-case: Go through the JavaScript implementation. |
7456 __ bind(&slow); | 7479 __ bind(&slow); |
7457 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 7480 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
7458 } | 7481 } |
7459 | 7482 |
7460 | 7483 |
7461 #undef __ | 7484 #undef __ |
7462 | 7485 |
7463 } } // namespace v8::internal | 7486 } } // namespace v8::internal |
OLD | NEW |