| 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 4587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4598 // context slot declaration, but we cannot initialize it at the same | 4598 // context slot declaration, but we cannot initialize it at the same |
| 4599 // time, because the const declaration may be at the end of the eval | 4599 // time, because the const declaration may be at the end of the eval |
| 4600 // code (sigh...) and the const variable may have been used before | 4600 // code (sigh...) and the const variable may have been used before |
| 4601 // (where its value is 'undefined'). Thus, we can only do the | 4601 // (where its value is 'undefined'). Thus, we can only do the |
| 4602 // initialization when we actually encounter the expression and when | 4602 // initialization when we actually encounter the expression and when |
| 4603 // the expression operands are defined and valid, and thus we need the | 4603 // the expression operands are defined and valid, and thus we need the |
| 4604 // split into 2 operations: declaration of the context slot followed | 4604 // split into 2 operations: declaration of the context slot followed |
| 4605 // by initialization. | 4605 // by initialization. |
| 4606 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 4606 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 4607 } else { | 4607 } else { |
| 4608 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3); | 4608 frame_->Push(Smi::FromInt(strict_mode_flag())); |
| 4609 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4); |
| 4609 } | 4610 } |
| 4610 // Storing a variable must keep the (new) value on the expression | 4611 // Storing a variable must keep the (new) value on the expression |
| 4611 // stack. This is necessary for compiling chained assignment | 4612 // stack. This is necessary for compiling chained assignment |
| 4612 // expressions. | 4613 // expressions. |
| 4613 frame_->Push(&value); | 4614 frame_->Push(&value); |
| 4614 } else { | 4615 } else { |
| 4615 ASSERT(!slot->var()->is_dynamic()); | 4616 ASSERT(!slot->var()->is_dynamic()); |
| 4616 | 4617 |
| 4617 JumpTarget exit; | 4618 JumpTarget exit; |
| 4618 if (init_state == CONST_INIT) { | 4619 if (init_state == CONST_INIT) { |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4907 break; | 4908 break; |
| 4908 } | 4909 } |
| 4909 // Fall through | 4910 // Fall through |
| 4910 } | 4911 } |
| 4911 case ObjectLiteral::Property::PROTOTYPE: { | 4912 case ObjectLiteral::Property::PROTOTYPE: { |
| 4912 // Duplicate the object as an argument to the runtime call. | 4913 // Duplicate the object as an argument to the runtime call. |
| 4913 frame_->Dup(); | 4914 frame_->Dup(); |
| 4914 Load(property->key()); | 4915 Load(property->key()); |
| 4915 Load(property->value()); | 4916 Load(property->value()); |
| 4916 if (property->emit_store()) { | 4917 if (property->emit_store()) { |
| 4918 frame_->Push(Smi::FromInt(NONE)); // PropertyAttributes |
| 4917 // Ignore the result. | 4919 // Ignore the result. |
| 4918 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3); | 4920 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4); |
| 4919 } else { | 4921 } else { |
| 4920 frame_->Drop(3); | 4922 frame_->Drop(3); |
| 4921 } | 4923 } |
| 4922 break; | 4924 break; |
| 4923 } | 4925 } |
| 4924 case ObjectLiteral::Property::SETTER: { | 4926 case ObjectLiteral::Property::SETTER: { |
| 4925 // Duplicate the object as an argument to the runtime call. | 4927 // Duplicate the object as an argument to the runtime call. |
| 4926 frame_->Dup(); | 4928 frame_->Dup(); |
| 4927 Load(property->key()); | 4929 Load(property->key()); |
| 4928 frame_->Push(Smi::FromInt(1)); | 4930 frame_->Push(Smi::FromInt(1)); |
| (...skipping 3136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8065 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); | 8067 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); |
| 8066 | 8068 |
| 8067 if (!dst_.is(rax)) __ movq(dst_, rax); | 8069 if (!dst_.is(rax)) __ movq(dst_, rax); |
| 8068 } | 8070 } |
| 8069 | 8071 |
| 8070 | 8072 |
| 8071 class DeferredReferenceSetKeyedValue: public DeferredCode { | 8073 class DeferredReferenceSetKeyedValue: public DeferredCode { |
| 8072 public: | 8074 public: |
| 8073 DeferredReferenceSetKeyedValue(Register value, | 8075 DeferredReferenceSetKeyedValue(Register value, |
| 8074 Register key, | 8076 Register key, |
| 8075 Register receiver) | 8077 Register receiver, |
| 8076 : value_(value), key_(key), receiver_(receiver) { | 8078 StrictModeFlag strict) |
| 8079 : value_(value), key_(key), receiver_(receiver), strict_(strict) { |
| 8077 set_comment("[ DeferredReferenceSetKeyedValue"); | 8080 set_comment("[ DeferredReferenceSetKeyedValue"); |
| 8078 } | 8081 } |
| 8079 | 8082 |
| 8080 virtual void Generate(); | 8083 virtual void Generate(); |
| 8081 | 8084 |
| 8082 Label* patch_site() { return &patch_site_; } | 8085 Label* patch_site() { return &patch_site_; } |
| 8083 | 8086 |
| 8084 private: | 8087 private: |
| 8085 Register value_; | 8088 Register value_; |
| 8086 Register key_; | 8089 Register key_; |
| 8087 Register receiver_; | 8090 Register receiver_; |
| 8088 Label patch_site_; | 8091 Label patch_site_; |
| 8092 StrictModeFlag strict_; |
| 8089 }; | 8093 }; |
| 8090 | 8094 |
| 8091 | 8095 |
| 8092 void DeferredReferenceSetKeyedValue::Generate() { | 8096 void DeferredReferenceSetKeyedValue::Generate() { |
| 8093 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); | 8097 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); |
| 8094 // Move value, receiver, and key to registers rax, rdx, and rcx, as | 8098 // Move value, receiver, and key to registers rax, rdx, and rcx, as |
| 8095 // the IC stub expects. | 8099 // the IC stub expects. |
| 8096 // Move value to rax, using xchg if the receiver or key is in rax. | 8100 // Move value to rax, using xchg if the receiver or key is in rax. |
| 8097 if (!value_.is(rax)) { | 8101 if (!value_.is(rax)) { |
| 8098 if (!receiver_.is(rax) && !key_.is(rax)) { | 8102 if (!receiver_.is(rax) && !key_.is(rax)) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8130 __ movq(rcx, key_); | 8134 __ movq(rcx, key_); |
| 8131 } | 8135 } |
| 8132 } else if (key_.is(rcx)) { | 8136 } else if (key_.is(rcx)) { |
| 8133 __ movq(rdx, receiver_); | 8137 __ movq(rdx, receiver_); |
| 8134 } else { | 8138 } else { |
| 8135 __ movq(rcx, key_); | 8139 __ movq(rcx, key_); |
| 8136 __ movq(rdx, receiver_); | 8140 __ movq(rdx, receiver_); |
| 8137 } | 8141 } |
| 8138 | 8142 |
| 8139 // Call the IC stub. | 8143 // Call the IC stub. |
| 8140 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 8144 Handle<Code> ic(Builtins::builtin( |
| 8145 strict_ == kStrictMode ? Builtins::KeyedStoreIC_Initialize_Strict |
| 8146 : Builtins::KeyedStoreIC_Initialize)); |
| 8141 __ Call(ic, RelocInfo::CODE_TARGET); | 8147 __ Call(ic, RelocInfo::CODE_TARGET); |
| 8142 // The delta from the start of the map-compare instructions (initial movq) | 8148 // The delta from the start of the map-compare instructions (initial movq) |
| 8143 // to the test instruction. We use masm_-> directly here instead of the | 8149 // to the test instruction. We use masm_-> directly here instead of the |
| 8144 // __ macro because the macro sometimes uses macro expansion to turn | 8150 // __ macro because the macro sometimes uses macro expansion to turn |
| 8145 // into something that can't return a value. This is encountered | 8151 // into something that can't return a value. This is encountered |
| 8146 // when doing generated code coverage tests. | 8152 // when doing generated code coverage tests. |
| 8147 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); | 8153 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); |
| 8148 // Here we use masm_-> instead of the __ macro because this is the | 8154 // Here we use masm_-> instead of the __ macro because this is the |
| 8149 // instruction that gets patched and coverage code gets in the way. | 8155 // instruction that gets patched and coverage code gets in the way. |
| 8150 masm_->testl(rax, Immediate(-delta_to_patch_site)); | 8156 masm_->testl(rax, Immediate(-delta_to_patch_site)); |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8471 bool value_is_constant = result.is_constant(); | 8477 bool value_is_constant = result.is_constant(); |
| 8472 | 8478 |
| 8473 // Make sure that value, key and receiver are in registers. | 8479 // Make sure that value, key and receiver are in registers. |
| 8474 result.ToRegister(); | 8480 result.ToRegister(); |
| 8475 key.ToRegister(); | 8481 key.ToRegister(); |
| 8476 receiver.ToRegister(); | 8482 receiver.ToRegister(); |
| 8477 | 8483 |
| 8478 DeferredReferenceSetKeyedValue* deferred = | 8484 DeferredReferenceSetKeyedValue* deferred = |
| 8479 new DeferredReferenceSetKeyedValue(result.reg(), | 8485 new DeferredReferenceSetKeyedValue(result.reg(), |
| 8480 key.reg(), | 8486 key.reg(), |
| 8481 receiver.reg()); | 8487 receiver.reg(), |
| 8488 strict_mode_flag()); |
| 8482 | 8489 |
| 8483 // Check that the receiver is not a smi. | 8490 // Check that the receiver is not a smi. |
| 8484 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); | 8491 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); |
| 8485 | 8492 |
| 8486 // Check that the key is a smi. | 8493 // Check that the key is a smi. |
| 8487 if (!key.is_smi()) { | 8494 if (!key.is_smi()) { |
| 8488 __ JumpIfNotSmi(key.reg(), deferred->entry_label()); | 8495 __ JumpIfNotSmi(key.reg(), deferred->entry_label()); |
| 8489 } else if (FLAG_debug_code) { | 8496 } else if (FLAG_debug_code) { |
| 8490 __ AbortIfNotSmi(key.reg()); | 8497 __ AbortIfNotSmi(key.reg()); |
| 8491 } | 8498 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8533 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); | 8540 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); |
| 8534 __ movq(FieldOperand(tmp.reg(), | 8541 __ movq(FieldOperand(tmp.reg(), |
| 8535 index.reg, | 8542 index.reg, |
| 8536 index.scale, | 8543 index.scale, |
| 8537 FixedArray::kHeaderSize), | 8544 FixedArray::kHeaderSize), |
| 8538 result.reg()); | 8545 result.reg()); |
| 8539 __ IncrementCounter(&Counters::keyed_store_inline, 1); | 8546 __ IncrementCounter(&Counters::keyed_store_inline, 1); |
| 8540 | 8547 |
| 8541 deferred->BindExit(); | 8548 deferred->BindExit(); |
| 8542 } else { | 8549 } else { |
| 8543 result = frame()->CallKeyedStoreIC(); | 8550 result = frame()->CallKeyedStoreIC(strict_mode_flag()); |
| 8544 // Make sure that we do not have a test instruction after the | 8551 // Make sure that we do not have a test instruction after the |
| 8545 // call. A test instruction after the call is used to | 8552 // call. A test instruction after the call is used to |
| 8546 // indicate that we have generated an inline version of the | 8553 // indicate that we have generated an inline version of the |
| 8547 // keyed store. | 8554 // keyed store. |
| 8548 __ nop(); | 8555 __ nop(); |
| 8549 } | 8556 } |
| 8550 ASSERT(frame()->height() == original_height - 3); | 8557 ASSERT(frame()->height() == original_height - 3); |
| 8551 return result; | 8558 return result; |
| 8552 } | 8559 } |
| 8553 | 8560 |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8812 } | 8819 } |
| 8813 | 8820 |
| 8814 #endif | 8821 #endif |
| 8815 | 8822 |
| 8816 | 8823 |
| 8817 #undef __ | 8824 #undef __ |
| 8818 | 8825 |
| 8819 } } // namespace v8::internal | 8826 } } // namespace v8::internal |
| 8820 | 8827 |
| 8821 #endif // V8_TARGET_ARCH_X64 | 8828 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |