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 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1931 } | 1931 } |
1932 node->break_target()->Unuse(); | 1932 node->break_target()->Unuse(); |
1933 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 1933 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
1934 } | 1934 } |
1935 | 1935 |
1936 | 1936 |
1937 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 1937 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
1938 frame_->EmitPush(cp); | 1938 frame_->EmitPush(cp); |
1939 frame_->EmitPush(Operand(pairs)); | 1939 frame_->EmitPush(Operand(pairs)); |
1940 frame_->EmitPush(Operand(Smi::FromInt(is_eval() ? 1 : 0))); | 1940 frame_->EmitPush(Operand(Smi::FromInt(is_eval() ? 1 : 0))); |
| 1941 frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag()))); |
1941 | 1942 |
1942 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | 1943 frame_->CallRuntime(Runtime::kDeclareGlobals, 4); |
1943 // The result is discarded. | 1944 // The result is discarded. |
1944 } | 1945 } |
1945 | 1946 |
1946 | 1947 |
1947 void CodeGenerator::VisitDeclaration(Declaration* node) { | 1948 void CodeGenerator::VisitDeclaration(Declaration* node) { |
1948 #ifdef DEBUG | 1949 #ifdef DEBUG |
1949 int original_height = frame_->height(); | 1950 int original_height = frame_->height(); |
1950 #endif | 1951 #endif |
1951 Comment cmnt(masm_, "[ Declaration"); | 1952 Comment cmnt(masm_, "[ Declaration"); |
1952 Variable* var = node->proxy()->var(); | 1953 Variable* var = node->proxy()->var(); |
(...skipping 1327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3280 // context slot declaration, but we cannot initialize it at the | 3281 // context slot declaration, but we cannot initialize it at the |
3281 // same time, because the const declaration may be at the end of | 3282 // same time, because the const declaration may be at the end of |
3282 // the eval code (sigh...) and the const variable may have been | 3283 // the eval code (sigh...) and the const variable may have been |
3283 // used before (where its value is 'undefined'). Thus, we can only | 3284 // used before (where its value is 'undefined'). Thus, we can only |
3284 // do the initialization when we actually encounter the expression | 3285 // do the initialization when we actually encounter the expression |
3285 // and when the expression operands are defined and valid, and | 3286 // and when the expression operands are defined and valid, and |
3286 // thus we need the split into 2 operations: declaration of the | 3287 // thus we need the split into 2 operations: declaration of the |
3287 // context slot followed by initialization. | 3288 // context slot followed by initialization. |
3288 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 3289 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
3289 } else { | 3290 } else { |
3290 frame_->CallRuntime(Runtime::kStoreContextSlot, 3); | 3291 frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag()))); |
| 3292 frame_->CallRuntime(Runtime::kStoreContextSlot, 4); |
3291 } | 3293 } |
3292 // Storing a variable must keep the (new) value on the expression | 3294 // Storing a variable must keep the (new) value on the expression |
3293 // stack. This is necessary for compiling assignment expressions. | 3295 // stack. This is necessary for compiling assignment expressions. |
3294 frame_->EmitPush(r0); | 3296 frame_->EmitPush(r0); |
3295 | 3297 |
3296 } else { | 3298 } else { |
3297 ASSERT(!slot->var()->is_dynamic()); | 3299 ASSERT(!slot->var()->is_dynamic()); |
3298 Register scratch = VirtualFrame::scratch0(); | 3300 Register scratch = VirtualFrame::scratch0(); |
3299 Register scratch2 = VirtualFrame::scratch1(); | 3301 Register scratch2 = VirtualFrame::scratch1(); |
3300 | 3302 |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3630 frame_->Drop(); | 3632 frame_->Drop(); |
3631 } | 3633 } |
3632 break; | 3634 break; |
3633 } | 3635 } |
3634 // else fall through | 3636 // else fall through |
3635 case ObjectLiteral::Property::PROTOTYPE: { | 3637 case ObjectLiteral::Property::PROTOTYPE: { |
3636 frame_->Dup(); | 3638 frame_->Dup(); |
3637 Load(key); | 3639 Load(key); |
3638 Load(value); | 3640 Load(value); |
3639 if (property->emit_store()) { | 3641 if (property->emit_store()) { |
3640 frame_->CallRuntime(Runtime::kSetProperty, 3); | 3642 frame_->EmitPush(Operand(Smi::FromInt(NONE))); // PropertyAttributes |
| 3643 frame_->CallRuntime(Runtime::kSetProperty, 4); |
3641 } else { | 3644 } else { |
3642 frame_->Drop(3); | 3645 frame_->Drop(3); |
3643 } | 3646 } |
3644 break; | 3647 break; |
3645 } | 3648 } |
3646 case ObjectLiteral::Property::SETTER: { | 3649 case ObjectLiteral::Property::SETTER: { |
3647 frame_->Dup(); | 3650 frame_->Dup(); |
3648 Load(key); | 3651 Load(key); |
3649 frame_->EmitPush(Operand(Smi::FromInt(1))); | 3652 frame_->EmitPush(Operand(Smi::FromInt(1))); |
3650 Load(value); | 3653 Load(value); |
(...skipping 3016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6667 // deferred code. | 6670 // deferred code. |
6668 __ BlockConstPoolFor(1); | 6671 __ BlockConstPoolFor(1); |
6669 } | 6672 } |
6670 } | 6673 } |
6671 | 6674 |
6672 | 6675 |
6673 class DeferredReferenceSetKeyedValue: public DeferredCode { | 6676 class DeferredReferenceSetKeyedValue: public DeferredCode { |
6674 public: | 6677 public: |
6675 DeferredReferenceSetKeyedValue(Register value, | 6678 DeferredReferenceSetKeyedValue(Register value, |
6676 Register key, | 6679 Register key, |
6677 Register receiver) | 6680 Register receiver, |
6678 : value_(value), key_(key), receiver_(receiver) { | 6681 StrictModeFlag strict) |
| 6682 : value_(value), key_(key), receiver_(receiver), strict_(strict) { |
6679 set_comment("[ DeferredReferenceSetKeyedValue"); | 6683 set_comment("[ DeferredReferenceSetKeyedValue"); |
6680 } | 6684 } |
6681 | 6685 |
6682 virtual void Generate(); | 6686 virtual void Generate(); |
6683 | 6687 |
6684 private: | 6688 private: |
6685 Register value_; | 6689 Register value_; |
6686 Register key_; | 6690 Register key_; |
6687 Register receiver_; | 6691 Register receiver_; |
| 6692 StrictModeFlag strict_; |
6688 }; | 6693 }; |
6689 | 6694 |
6690 | 6695 |
6691 void DeferredReferenceSetKeyedValue::Generate() { | 6696 void DeferredReferenceSetKeyedValue::Generate() { |
6692 Register scratch1 = VirtualFrame::scratch0(); | 6697 Register scratch1 = VirtualFrame::scratch0(); |
6693 Register scratch2 = VirtualFrame::scratch1(); | 6698 Register scratch2 = VirtualFrame::scratch1(); |
6694 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2); | 6699 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2); |
6695 __ IncrementCounter( | 6700 __ IncrementCounter( |
6696 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2); | 6701 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2); |
6697 | 6702 |
6698 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic | 6703 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic |
6699 // calling convention. | 6704 // calling convention. |
6700 if (value_.is(r1)) { | 6705 if (value_.is(r1)) { |
6701 __ Swap(r0, r1, ip); | 6706 __ Swap(r0, r1, ip); |
6702 } | 6707 } |
6703 ASSERT(receiver_.is(r2)); | 6708 ASSERT(receiver_.is(r2)); |
6704 | 6709 |
6705 // The rest of the instructions in the deferred code must be together. | 6710 // The rest of the instructions in the deferred code must be together. |
6706 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6711 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
6707 // Call keyed store IC. It has the arguments value, key and receiver in r0, | 6712 // Call keyed store IC. It has the arguments value, key and receiver in r0, |
6708 // r1 and r2. | 6713 // r1 and r2. |
6709 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 6714 Handle<Code> ic(Builtins::builtin( |
| 6715 strict_ == kStrictMode ? Builtins::KeyedStoreIC_Initialize_Strict |
| 6716 : Builtins::KeyedStoreIC_Initialize)); |
6710 __ Call(ic, RelocInfo::CODE_TARGET); | 6717 __ Call(ic, RelocInfo::CODE_TARGET); |
6711 // The call must be followed by a nop instruction to indicate that the | 6718 // The call must be followed by a nop instruction to indicate that the |
6712 // keyed store has been inlined. | 6719 // keyed store has been inlined. |
6713 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); | 6720 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); |
6714 | 6721 |
6715 // Block the constant pool for one more instruction after leaving this | 6722 // Block the constant pool for one more instruction after leaving this |
6716 // constant pool block scope to include the branch instruction ending the | 6723 // constant pool block scope to include the branch instruction ending the |
6717 // deferred code. | 6724 // deferred code. |
6718 __ BlockConstPoolFor(1); | 6725 __ BlockConstPoolFor(1); |
6719 } | 6726 } |
6720 } | 6727 } |
6721 | 6728 |
6722 | 6729 |
6723 class DeferredReferenceSetNamedValue: public DeferredCode { | 6730 class DeferredReferenceSetNamedValue: public DeferredCode { |
6724 public: | 6731 public: |
6725 DeferredReferenceSetNamedValue(Register value, | 6732 DeferredReferenceSetNamedValue(Register value, |
6726 Register receiver, | 6733 Register receiver, |
6727 Handle<String> name) | 6734 Handle<String> name, |
6728 : value_(value), receiver_(receiver), name_(name) { | 6735 StrictModeFlag strict) |
| 6736 : value_(value), receiver_(receiver), name_(name), strict_(strict) { |
6729 set_comment("[ DeferredReferenceSetNamedValue"); | 6737 set_comment("[ DeferredReferenceSetNamedValue"); |
6730 } | 6738 } |
6731 | 6739 |
6732 virtual void Generate(); | 6740 virtual void Generate(); |
6733 | 6741 |
6734 private: | 6742 private: |
6735 Register value_; | 6743 Register value_; |
6736 Register receiver_; | 6744 Register receiver_; |
6737 Handle<String> name_; | 6745 Handle<String> name_; |
| 6746 StrictModeFlag strict_; |
6738 }; | 6747 }; |
6739 | 6748 |
6740 | 6749 |
6741 // Takes value in r0, receiver in r1 and returns the result (the | 6750 // Takes value in r0, receiver in r1 and returns the result (the |
6742 // value) in r0. | 6751 // value) in r0. |
6743 void DeferredReferenceSetNamedValue::Generate() { | 6752 void DeferredReferenceSetNamedValue::Generate() { |
6744 // Record the entry frame and spill. | 6753 // Record the entry frame and spill. |
6745 VirtualFrame copied_frame(*frame_state()->frame()); | 6754 VirtualFrame copied_frame(*frame_state()->frame()); |
6746 copied_frame.SpillAll(); | 6755 copied_frame.SpillAll(); |
6747 | 6756 |
6748 // Ensure value in r0, receiver in r1 to match store ic calling | 6757 // Ensure value in r0, receiver in r1 to match store ic calling |
6749 // convention. | 6758 // convention. |
6750 ASSERT(value_.is(r0) && receiver_.is(r1)); | 6759 ASSERT(value_.is(r0) && receiver_.is(r1)); |
6751 __ mov(r2, Operand(name_)); | 6760 __ mov(r2, Operand(name_)); |
6752 | 6761 |
6753 // The rest of the instructions in the deferred code must be together. | 6762 // The rest of the instructions in the deferred code must be together. |
6754 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6763 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
6755 // Call keyed store IC. It has the arguments value, key and receiver in r0, | 6764 // Call keyed store IC. It has the arguments value, key and receiver in r0, |
6756 // r1 and r2. | 6765 // r1 and r2. |
6757 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 6766 Handle<Code> ic(Builtins::builtin( |
| 6767 strict_ == kStrictMode ? Builtins::StoreIC_Initialize_Strict |
| 6768 : Builtins::StoreIC_Initialize)); |
6758 __ Call(ic, RelocInfo::CODE_TARGET); | 6769 __ Call(ic, RelocInfo::CODE_TARGET); |
6759 // The call must be followed by a nop instruction to indicate that the | 6770 // The call must be followed by a nop instruction to indicate that the |
6760 // named store has been inlined. | 6771 // named store has been inlined. |
6761 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); | 6772 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); |
6762 | 6773 |
6763 // Go back to the frame we entered with. The instructions | 6774 // Go back to the frame we entered with. The instructions |
6764 // generated by this merge are skipped over by the inline store | 6775 // generated by this merge are skipped over by the inline store |
6765 // patching mechanism when looking for the branch instruction that | 6776 // patching mechanism when looking for the branch instruction that |
6766 // tells it where the code to patch is. | 6777 // tells it where the code to patch is. |
6767 copied_frame.MergeTo(frame_state()->frame()); | 6778 copied_frame.MergeTo(frame_state()->frame()); |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6936 // Inline the in-object property case. | 6947 // Inline the in-object property case. |
6937 JumpTarget slow, done; | 6948 JumpTarget slow, done; |
6938 | 6949 |
6939 // Get the value and receiver from the stack. | 6950 // Get the value and receiver from the stack. |
6940 frame()->PopToR0(); | 6951 frame()->PopToR0(); |
6941 Register value = r0; | 6952 Register value = r0; |
6942 frame()->PopToR1(); | 6953 frame()->PopToR1(); |
6943 Register receiver = r1; | 6954 Register receiver = r1; |
6944 | 6955 |
6945 DeferredReferenceSetNamedValue* deferred = | 6956 DeferredReferenceSetNamedValue* deferred = |
6946 new DeferredReferenceSetNamedValue(value, receiver, name); | 6957 new DeferredReferenceSetNamedValue( |
| 6958 value, receiver, name, strict_mode_flag()); |
6947 | 6959 |
6948 // Check that the receiver is a heap object. | 6960 // Check that the receiver is a heap object. |
6949 __ tst(receiver, Operand(kSmiTagMask)); | 6961 __ tst(receiver, Operand(kSmiTagMask)); |
6950 deferred->Branch(eq); | 6962 deferred->Branch(eq); |
6951 | 6963 |
6952 // The following instructions are the part of the inlined | 6964 // The following instructions are the part of the inlined |
6953 // in-object property store code which can be patched. Therefore | 6965 // in-object property store code which can be patched. Therefore |
6954 // the exact number of instructions generated must be fixed, so | 6966 // the exact number of instructions generated must be fixed, so |
6955 // the constant pool is blocked while generating this code. | 6967 // the constant pool is blocked while generating this code. |
6956 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6968 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7122 VirtualFrame::SpilledScope spilled(frame_); | 7134 VirtualFrame::SpilledScope spilled(frame_); |
7123 Register receiver = r2; | 7135 Register receiver = r2; |
7124 frame_->EmitPop(receiver); | 7136 frame_->EmitPop(receiver); |
7125 | 7137 |
7126 #ifdef DEBUG | 7138 #ifdef DEBUG |
7127 bool we_remembered_the_write_barrier = value_is_harmless; | 7139 bool we_remembered_the_write_barrier = value_is_harmless; |
7128 #endif | 7140 #endif |
7129 | 7141 |
7130 // The deferred code expects value, key and receiver in registers. | 7142 // The deferred code expects value, key and receiver in registers. |
7131 DeferredReferenceSetKeyedValue* deferred = | 7143 DeferredReferenceSetKeyedValue* deferred = |
7132 new DeferredReferenceSetKeyedValue(value, key, receiver); | 7144 new DeferredReferenceSetKeyedValue( |
| 7145 value, key, receiver, strict_mode_flag()); |
7133 | 7146 |
7134 // Check that the value is a smi. As this inlined code does not set the | 7147 // Check that the value is a smi. As this inlined code does not set the |
7135 // write barrier it is only possible to store smi values. | 7148 // write barrier it is only possible to store smi values. |
7136 if (!value_is_harmless) { | 7149 if (!value_is_harmless) { |
7137 // If the value is not likely to be a Smi then let's test the fixed array | 7150 // If the value is not likely to be a Smi then let's test the fixed array |
7138 // for new space instead. See below. | 7151 // for new space instead. See below. |
7139 if (wb_info == LIKELY_SMI) { | 7152 if (wb_info == LIKELY_SMI) { |
7140 __ tst(value, Operand(kSmiTagMask)); | 7153 __ tst(value, Operand(kSmiTagMask)); |
7141 deferred->Branch(ne); | 7154 deferred->Branch(ne); |
7142 #ifdef DEBUG | 7155 #ifdef DEBUG |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7207 | 7220 |
7208 // Make sure that the expected number of instructions are generated. | 7221 // Make sure that the expected number of instructions are generated. |
7209 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch, | 7222 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch, |
7210 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); | 7223 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); |
7211 } | 7224 } |
7212 | 7225 |
7213 ASSERT(we_remembered_the_write_barrier); | 7226 ASSERT(we_remembered_the_write_barrier); |
7214 | 7227 |
7215 deferred->BindExit(); | 7228 deferred->BindExit(); |
7216 } else { | 7229 } else { |
7217 frame()->CallKeyedStoreIC(); | 7230 frame()->CallKeyedStoreIC(strict_mode_flag()); |
7218 } | 7231 } |
7219 } | 7232 } |
7220 | 7233 |
7221 | 7234 |
7222 #ifdef DEBUG | 7235 #ifdef DEBUG |
7223 bool CodeGenerator::HasValidEntryRegisters() { return true; } | 7236 bool CodeGenerator::HasValidEntryRegisters() { return true; } |
7224 #endif | 7237 #endif |
7225 | 7238 |
7226 | 7239 |
7227 #undef __ | 7240 #undef __ |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7375 BinaryOpIC::GetName(runtime_operands_type_)); | 7388 BinaryOpIC::GetName(runtime_operands_type_)); |
7376 return name_; | 7389 return name_; |
7377 } | 7390 } |
7378 | 7391 |
7379 | 7392 |
7380 #undef __ | 7393 #undef __ |
7381 | 7394 |
7382 } } // namespace v8::internal | 7395 } } // namespace v8::internal |
7383 | 7396 |
7384 #endif // V8_TARGET_ARCH_ARM | 7397 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |