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 |